基于路由器参数获取w/自定义React钩子



我正试图根据当前路由器参数,使用自定义React钩子获取数据。

https://stackblitz.com/edit/react-fetch-router

它应该做什么:

第一次加载时,检查URL是否包含ID…

  • 如果是,获取具有该ID的todo
  • 如果没有,则获取一个带有随机ID&将ID添加到url

点击获取按钮。。。

  • 获取一个带有随机ID的todo;将ID添加到url

出了什么问题:

观察控制台或检查器网络选项卡,您可以看到它在每次单击时都会触发几个获取请求——为什么要这样做,以及应该如何正确执行?

由于您在handleClick上使用了history.push,您将看到在使用history.push点击处理程序时发送了多个请求,这将导致重新渲染,并使用随机生成的url,同时触发fetchTodo函数。

现在将进行重新渲染,这将导致生成一个随机id。并传递到useTodo钩子上,这将导致再次调用fetchTodo函数。

正确的解决方案是在handleClick上设置随机todo id参数,并避免不必要的url更新

const Todos = () => {
const history = useHistory();
const { id: todoId } = useParams();
const { fetchTodo, todo, isFetching, error } = useTodo(todoId);
const isInitialRender = useRef(true);
const handleClick = () => {
const todoId = randomMax(100);
history.push(`/${todoId}`);
};

useEffect(() => {
history.push(`/${todoId}`);
}, []);
useEffect(() => {
if(!isInitialRender.current) {
fetchTodo();
} else {
isInitialRender.current = false
}
}, [todoId])
return (
<>
<button onClick={handleClick} style={{marginBottom: "10px"}}>Fetch a todo</button>
{isFetching ? (
<p>Fetching...</p>
) : (
<Todo todo={todo} color={todo.color} isFetching={isFetching} />
)
}
</>
);
};
export default Todos;

工作演示

最新更新