我正在尝试开发一个React应用程序,该应用程序调用数据库将一组页面加载到板上以构建拖放决策树。我才刚刚开始使用React,所以很想听听我在这里做错了什么。
使用'useEffect', pageTree函数将在第一次加载和每次刷新时加载页面,但是页面状态返回一个空数组而不是当前页面。奇怪的是,所有的页码都和页码一起显示在黑板上。地图功能的工作在页面状态…(在console.log…上返回空值)
如果我在数组中添加一个页面,它会将更改保存到数据库中,但随后只会在板上显示新页面。然后,您必须刷新才能看到新的页面集(包括添加的页面)。
添加或删除页面的调用由父组件中的布局菜单按钮调用。
刷新后的控制台
另外,如果我移动一个页面,状态将控制OK:
移动页后控制台中页的状态。数据库调用和状态更新工作正常
function PageTree({AddNewPageFunc}) {
const [pages, setPages] = useState([]);
const movePage = useCallback((droppedPage) => {
const updatedPages = pages.map(page => droppedPage._id == page._id ? droppedPage : page);
setPages(updatedPages);
}, [pages]);
const [{isOver}, drop] = useDrop(() => ({
accept: ItemTypes.PAGECARD,
drop(page, monitor) {
const delta = monitor.getDifferenceFromInitialOffset();
let x = Math.round(page.x + delta.x);
let y = Math.round(page.y + delta.y);
page.x = x;
page.y = y;
movePage(page);
setNewPagePosition(page);
return undefined;
},
}), [movePage]);
const setNewPagePosition = async (pageDetails) => {
console.log("function called to update page position");
Api.withToken().post('/pageupdate/'+pageDetails._id,
pageDetails
).then(function (response) {
console.log("moved page: ",response.data)
}).catch(function (error) {
//console.log(error);
});
}
React.useEffect(() => {
AddNewPageFunc.current = AddNewPage
}, [])
const AddNewPage = useCallback(() => {
console.log("calling add new page function")
console.log("the pages before the API call are ",pages)
Api.withToken().post('/addblankpage/'
).then(function (response) {
console.log("produced: ",response.data);
setPages(pages.concat(response.data))
console.log("the pages after updating state are: ",pages)
}).catch(function (error) {
//console.log(error);
});
}, [pages]);
const handleDelete = async (id) => {
Api.withToken().post('/deletepages/'+id
).then(function (response) {
let index = pages.findIndex(function(item){
return item.id === response.data._id;
});
const PageRemoved = pages.splice(index, 1);
setPages(PageRemoved);
}).catch(function (error) {
//console.log(error);
});
}
useEffect(() => {
Api.withToken().get('/pages/')
.then(res => {
setPages(res.data);
console.log('res data ',res.data);
console.log('pages ',pages);
})
}, []);
return (
<div ref={drop} style={styles}>
{pages.map((page) => (<PageCard page={page} id={page._id} key={page._id} handleDelete={() => handleDelete(page._id)} handleMaximise={() => handleMaximise(page)} handleCopy={() => handleCopy(page)}/>))}
</div>
)
}
export default PageTree;
正如Danielprabhakaran指出的,问题在于React.useEffect中的回调。在添加新页面时,它需要将更新后的页面状态发送回父组件。在API调用后对状态使用console.log似乎很麻烦,即使使用.then(console.log(state)
function PageTree({AddNewPageFunc}) {
const [pages, setPages] = useState([]);
const movePage = useCallback((droppedPage) => {
const updatedPages = pages.map(page => droppedPage._id == page._id ? droppedPage : page);
console.log("updated pages ",updatedPages);
setPages(updatedPages);
console.log("set pages ",pages);
}, [pages]);
const [{isOver}, drop] = useDrop(() => ({
accept: ItemTypes.PAGECARD,
drop(page, monitor) {
const delta = monitor.getDifferenceFromInitialOffset();
let x = Math.round(page.x + delta.x);
let y = Math.round(page.y + delta.y);
page.x = x;
page.y = y;
movePage(page);
setNewPagePosition(page);
return undefined;
},
}), [movePage]);
const setNewPagePosition = async (pageDetails) => {
console.log("function called to update page position");
Api.withToken().post('/pageupdate/'+pageDetails._id,
pageDetails
).then(function (response) {
console.log("?worked ",response)
}).catch(function (error) {
//console.log(error);
});
}
React.useEffect(() => {
AddNewPageFunc.current = AddNewPage
}, [pages])
const AddNewPage = useCallback(() => {
console.log("calling add new page function")
console.log("the pages before the API call are ",pages)
Api.withToken().post('/addblankpage/'
).then(function (response) {
console.log("produced: ",response.data);
setPages(pages.concat(response.data))
console.log("the pages after updating state are: ",pages)
}).catch(function (error) {
//console.log(error);
});
}, [pages]);
const handleDeletedCallback = (deletedIndex) => {
console.log("delete callback fired")
setPages(pages.splice(deletedIndex, 1));
}
useEffect(() => {
Api.withToken().get('/pages/') //can add in a prop to return only a given tree once the app gets bigger
.then(res => {
setPages(res.data);
console.log('res data ',res.data);
console.log('pages ',pages);
})
}, []);
return (
<div ref={drop} style={styles}>
{pages.map((page, index) => (<PageCard page={page} id={page._id} key={page._id} index={index} deleteCallback={handleDeletedCallback} handleMaximise={() => handleMaximise(page)} handleCopy={() => handleCopy(page)}/>))}
</div>
)
}
export default PageTree;