假设我有一个App.jsx:
App.jsx
const App = () => {
return (
<React.Fragment>
<NavBar />
<BooksList />
<TextEditor />
</React.Fragment>
)
}
export default App;
BooksList
和TextEditor
是2个功能组件。在一个组件中,我能够将编辑器的内容保存到数据库中:
Editor.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()
在功能上等同于基于类的安装方法。这使我相信可以做到这一点。但是,我读过有状态组件应使用基于类的组件。
谢谢, 亚历克斯
答案 0 :(得分:0)
有几种不同的方法可以做到这一点,这都取决于组件的结构。最重要的是,当您成功发布到数据库时,您需要触发GET请求。一种快速,肮脏的解决方案是将GET请求移到一个单独的函数中,并在useEffect中调用它,并将该函数作为道具传递给下一个。像这样:
Editor.jsx
const SaveContent = ({ value, icon, refreshBooksList }) => {
const addBook = useCallback(async () => {
const response = await fetch('/add_book', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(value)
})
if (response.ok) {
console.log('response okay')
refreshBooksList()
}
}, [value, refreshBooksList])
return (
<SaveButton
onMouseDown={addBook}
>
<Icon icon={icon}></Icon>
</SaveButton>
)
}
BooksList.jsx
const BooksList = () => {
const [books, setBooks] = useState([]);
const getBooksList = useCallback(async () => {
await fetch('/get_books')
.then(response =>
response.json()
.then(data => {
setBooks(data)
})
);
}, [setBooks])
useEffect(() => {
getBooksList()
}, [])
return (
<*list of saved editors*>
)
}
如果两个组件都不是父级/子级,则需要将getBooks
函数在树上移动到共享的父级。
根据API返回的内容,您可以完全删除其他GET请求,而只需更新状态即可。如果是这种情况,可以考虑使用React Context来避免传递道具。
答案 1 :(得分:0)
如果您的Editor和BookList组件位于同一父组件内,则可以在Parent组件内使用状态。父级会将回调传递给编辑器。编辑器将使用此回调来通知父级有一本新书。父级将增加状态并将该状态作为道具传递给BookList。然后BookList将检查useEffect中的道具是否已更改,并重新加载书籍列表。
这是一个最小的代码示例:
const Parent = () => {
const [x, setX] = React.useState(0);
const onNewBook = () => {
setX(state => state+1);
}
return (
<>
<BookList x={X} />
<Editor onNewBook={onNewBook} />
</>
)
}
const Editor = (props) => {
onSave = () => {
// Save the editor to the DB
props.onNewBook();
}
}
const BookList= (props) => {
React.useEffect(() => {
// Reload the list from DB
}, [props.X])
}
答案 2 :(得分:0)
如果Editor和BookList不在同一个Parent组件内,则可以使用事件在Editor和BookList之间进行通信。编辑器可以发送事件,而BookList可以监听这些事件。
BookList
document.body.addEventListener('updateBookList', onUpdateBookList, false);
编辑器
const myEvent = new CustomEvent('updateBookList');
document.body.dispatchEvent(myEvent);