问题描述
我正在使用Node.js后端构建React + Redux应用程序,其中一项功能是用户可以查看其他用户的配置文件。为此,我在Redux state
中有一个名为users
的部分,如下所示:
{
...,users: {
user: {},isLoading: true
}
}
每次渲染/users/:id
路线时,都会调度getUser(id)
动作,并用接收到的信息填充状态。
主要问题是,当用户查看用户1的配置文件页面(因此现在用用户1的配置文件填充了redux状态)然后查看用户2的配置文件页面时,在页面呈现后立即调用dispatch getUser(2)
操作。由于user1的信息仍处于状态,因此它将在很短的时间内刷新其信息,然后显示加载微调框,直到加载新用户为止。
我读到有关在页面的每个未装载位置上调度resetUser(id)
操作的信息,但是我不确定这是否是正确的方法。此外,功能之一是,如果用户正在查看自己的页面,则可以使用编辑按钮将其重定向到/edit-profile
。如果我在每次卸载时都重置了状态,即使我在他们查看其页面时才这样做,也必须再次获取他们的配置文件(在编辑页面中)。这似乎没有道理。 / p>
任何想法如何解决这个问题?谢谢!
解决方法
render
阶段在mounting
之后运行。您说过,先前的数据将在新数据之前显示。看来您已经进行了异步安装:
async componentDidMount() {}
即使在安装阶段完成之前,它将继续渲染。为避免问题,您可以使用挂载的同步特性:
componentDidMount(){}
您将在哪里调用api数据。
现在,当您进入渲染阶段时,它将在渲染之前拥有新数据,并且不会刷新您的旧数据。
您现在可能想知道如何异步调用api。您可以创建一个异步函数,然后在同步componentDidMount内部调用该函数。
componentDidMount() {
yourAsyncFunc()
}
async yourAsyncFunc() {} // api call
我该如何使用React挂钩?
使用useEffect
时,请勿实现异步:
useEffect(async () =>
简单实施:
useEffect(() => {
// you can still use asynchronous function here
async function callApi() {}
callApi()
},[]) // [] to run in similar to componentDidMount
如果错过了useEffect
的第二个参数,则不能确保它在安装阶段运行。视情况而定,它将在渲染阶段之前,之后和之中运行。
实施类似resetUser(id)
之类的方法似乎是正确的方法。我在当前项目中使用了这种方法,这确实解决了问题。另一个答案中提到的从async
回调中删除useEffect
关键字的另一种方法对我不起作用(我使用钩子,redux-toolkit和Typescript)。
分派此操作后,您的状态应类似于
{
...,users: {
user: null,isLoading: false,}
}
如果您使用钩子,则可以通过以下方式分派操作:
useEffect(() => {
const ac = new AbortController();
...
return () => {
dispatch(resetUser(null));
ac.abort();
};
},[]);
动作可能看起来像这样:
resetListingDetails(state,action) {
// Immer-like mutable update
state.users = {
...state.users,user: null,};
}