reactjs - 如何从路由 url 获取数据以放入 React 路由器的回调函数中?
问题描述
我正在研究我的搜索功能。我想在路由中触发一个回调函数来获取所有数据,然后再进入搜索组件。
像这样:
<Route path="/search/:query" component={QuestionSearchContainer} onChange={()=>store.dispatch(fetchData(query?)) }/>
这是 QuestionSearchContainer:
const mapStateToProps = (state,ownProps) => {
return {
questions: Object.values(state.entities.questions),
currentUser: state.entities.users[state.session.id],
query: ownProps.match.params.query,
url: ownProps.match.url
}}
但是我怎样才能让搜索 url 中的查询关键字作为参数放入我的 fetchData 中呢?我想在转到 QuestionSearchContainer 之前获取数据并将其保存到 redux 存储,以便我可以获取容器中问题的所有数据。
解决方案
如果您不想使用 QuestionSearchContainer 组件进行数据提取,则可以制作一个高阶组件来包装它,以便为您提取数据。
您可以轻松地修改此 HOC 以仅在数据加载完成时返回 Wrapped 组件。加载部分假设 fetchData 是一个redux thunk action creator。useParams是从 react-router-dom 导出的钩子,可让您访问匹配参数。useDispatch是从 react-redux 导出的钩子,可让您访问商店的调度功能。
import { useParams } from 'react-router-dom';
import { useDispatch } from 'react-redux';
import { useEffect, useState } from 'react';
const withFetchData = (Component) => ({ children, ...props }) => {
const { query } = useParams();
const [loading, setLoading] = useState(true);
const dispatch = useDispatch();
useEffect(() => {
// Assuming fetchData is a a redux thunk action creator
setLoading(true);
dispatch(fetchData(query)).then(() => {
setLoading(false);
});
}, [query]);
if(loading){
return 'loading...'
}
return <Component {...props} />;
};
const QuestionSearchContainerWithFetchData = withFetchData(
QuestionSearchContainer
);
const Parent = () => {
return (
<Route
path="/search/:query"
component={QuestionSearchContainerWithFetchData}
/>
);
};
另一种选择是创建一条特殊的路线来满足您的需求。例如,onChangeParams
每次参数更改时,此 OnChangeRoute 函数都会使用当前参数调用回调。在这个中,您必须传入一个加载道具,因为组件本身并不关心您对参数所做的事情。
import { useEffect, useRef } from "react";
function InnerOnChangeRoute({ loading, onParamsChange, Component, ...rest }) {
const onChangeRef = useRef(onParamsChange);
useEffect(()=>{
onChangeRef.current=onParamsChange;
},[onParamsChange])
useEffect(() => {
onChangeRef.current(rest.match.params);
}, [rest.match.params]);
if(loading){
return 'loading....'
}
return <Component {...rest} />;
}
// A wrapper for <Route> that redirects to the login
// screen if you're not yet authenticated.
function OnChangeRoute({ Component, onParamsChange, loading, ...rest }) {
return (
<Route
{...rest}
render={(data) => (
<InnerOnChangeRoute
Component={Component}
onParamsChange={onParamsChange}
loading={loading}
{...data}
/>
)}
/>
);
}
一般来说,对于 redux,您必须使用 dispatch(或连接器 HOC 中的 mapDispatchToProps)来运行使用您的数据更新存储的操作。
这里有一些链接,希望能帮助你更好地控制 redux。
https://redux.js.org/advanced/async-actions
https://redux-toolkit.js.org/usage/usage-guide#asynchronous-logic-and-data-fetching