首页 > 解决方案 > 如何从路由 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 存储,以便我可以获取容器中问题的所有数据。

标签: reactjsrouter

解决方案


如果您不想使用 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

https://github.com/reduxjs/redux-thunk


推荐阅读