使用 useEffect() 管理功能组件的状态

假设我有一个 App.jsx:


应用程序.jsx


const App = () => {

    return (

        <React.Fragment>

            <NavBar />

            <BooksList />

            <TextEditor />

        </React.Fragment>

    )

}


export default App;



和是 2BooksList个TextEditor功能组件。在一个组件中,我能够将编辑器的内容保存到数据库中:


编辑器.jsx


const TextEditor = () => {

    return(

        <*editor related stuff*>

    )

}


const SaveContent = ({ value, icon }) => {

    return (

        <SaveButton

            onMouseDown={async () => {

                console.log(JSON.stringify(value));

                const response = await fetch('/add_book', {

                    method: 'POST',

                    headers: {

                        'Content-Type': 'application/json'

                    },


                    body: JSON.stringify(value)


                })


                if (response.ok) {

                    console.log('response okay')

                }

            }}

        >

            <Icon icon={icon}></Icon>

        </SaveButton>

    )

}


这成功写入我的数据库。


我想让 BookList 组件在我保存/删除项目时自动更新数据库的内容。这是我目前拥有的 BookList 组件:


BooksList.jsx


const BooksList = () => {

    const [books, setBooks] = useState([]);


    useEffect(() => {

        fetch('/get_books')

        .then(response => 

            response.json()

        .then(data => {

            setBooks(data)

        })

        );

    }, [])


    return (

        <*list of saved editors*>

    )

}

所以在加载时,如果数据库是空的,它什么也不显示。当我保存到数据库时,它什么也没显示,然后当我刷新页面时,它显示我想要取回的数据。我希望能够保存数据并自动看到上述组件刷新和更新。


我是 React 和 JS 的新手,所以任何指针都会很棒。我认为可能需要重写以使用基于类的组件来更轻松地管理状态?但我不确定。我的基本理解是,这useEffect()是基于类的安装方法的功能等价物。这让我相信这是可以做到的。但是,我读过有状态组件应该使用基于类的组件。



江户川乱折腾
浏览 180回答 3
3回答

哆啦的时光机

有几种不同的方法可以做到这一点,这完全取决于您的组件的结构。底线是,当您成功 POST 到数据库时,您需要触发您的 GET 请求。一个快速而肮脏的解决方案是将 GET 请求移到一个单独的函数中,并在 useEffect 中调用它,并将函数作为道具传递下去。像这样的东西:编辑器.jsxconst SaveContent = ({ value, icon, refreshBooksList }) => {&nbsp; &nbsp; const addBook = useCallback(async () => {&nbsp; &nbsp; &nbsp; &nbsp; const response = await fetch('/add_book', {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; method: 'POST',&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; headers: {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 'Content-Type': 'application/json'&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; body: JSON.stringify(value)&nbsp; &nbsp; &nbsp; &nbsp; })&nbsp; &nbsp; &nbsp; &nbsp; if (response.ok) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; console.log('response okay')&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; refreshBooksList()&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }, [value, refreshBooksList])&nbsp; &nbsp; return (&nbsp; &nbsp; &nbsp; &nbsp; <SaveButton&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; onMouseDown={addBook}&nbsp; &nbsp; &nbsp; &nbsp; >&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <Icon icon={icon}></Icon>&nbsp; &nbsp; &nbsp; &nbsp; </SaveButton>&nbsp; &nbsp; )}BooksList.jsxconst BooksList = () => {&nbsp; &nbsp; const [books, setBooks] = useState([]);&nbsp; &nbsp; const getBooksList = useCallback(async () => {&nbsp; &nbsp; &nbsp; &nbsp; await fetch('/get_books')&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .then(response =>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; response.json()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; .then(data => {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; setBooks(data)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; })&nbsp; &nbsp; &nbsp; &nbsp; );&nbsp; &nbsp; }, [setBooks])&nbsp; &nbsp; useEffect(() => {&nbsp; &nbsp; &nbsp; &nbsp; getBooksList()&nbsp; &nbsp; }, [])&nbsp; &nbsp; return (&nbsp; &nbsp; &nbsp; &nbsp; <*list of saved editors*>&nbsp; &nbsp; )}如果这两个组件不是父/子,那么您需要将getBooks函数向上移动到共享父级。根据 API 返回的内容,您可以完全删除额外的 GET 请求并简单地更新状态。如果是这种情况,您可以考虑使用 React Context 来避免传递道具。

元芳怎么了

如果 Editor 和 BookList 不在同一个 Parent 组件内,可以使用事件在 Editor 和 BookList 之间进行通信。Editor 可以发送事件,BookList 可以监听这些事件。书单document.body.addEventListener('updateBookList',&nbsp;onUpdateBookList,&nbsp;false);编辑const&nbsp;myEvent&nbsp;=&nbsp;new&nbsp;CustomEvent('updateBookList'); document.body.dispatchEvent(myEvent);

郎朗坤

如果您的 Editor 和 BookList 组件在同一个父组件内,那么您可以在 Parent 组件内使用状态。父级将回调传递给编辑器。编辑器将使用此回调通知 Parent 有一本新书。Parent 将增加状态并将该状态作为道具传递给 BookList。然后 BookList 会检查 useEffect 中的 props 是否发生了变化,并重新加载书籍列表。这是一个最小的代码示例:const Parent = () => {&nbsp; const [x, setX] = React.useState(0);&nbsp; const onNewBook = () => {&nbsp; &nbsp; setX(state => state+1);&nbsp; }&nbsp; return (&nbsp; &nbsp; <>&nbsp; &nbsp; &nbsp; <BookList x={X} />&nbsp; &nbsp; &nbsp; <Editor onNewBook={onNewBook} />&nbsp; &nbsp; </>&nbsp; )}const Editor = (props) => {&nbsp; onSave = () => {&nbsp; &nbsp; // Save the editor to the DB&nbsp; &nbsp; props.onNewBook();&nbsp; }}const BookList= (props) => {&nbsp; React.useEffect(() => {&nbsp; &nbsp; // Reload the list from DB&nbsp; }, [props.X])}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript