Как получить данные из URL маршрута, чтобы поместить их в функцию обратного вызова в маршрутизаторе React? - PullRequest
0 голосов
/ 02 мая 2020

Я работаю над своей функцией поиска. Я хочу вызвать функцию обратного вызова в маршруте для извлечения всех данных, прежде чем они попадут в поисковый компонент.

Примерно так:

<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, чтобы я мог получить все данные для вопросов в контейнере.

Ответы [ 2 ]

0 голосов
/ 02 мая 2020

Во-первых, Route не имеет обработчика onChange. (onEnter было доступно в предыдущих версиях (3 и более ранних) из react-router-dom

Поскольку ваше требование, по-видимому, указывается c для одного компонента (QuestionSearchContainer), использование пользовательских хуков или hocs может быть нецелесообразно. идеальное решение.

Вы можете просто использовать useEffect и прослушивать изменения URL (запрос). Вы можете получить query с помощью props.match.params и передать его в качестве аргумента в ваш обратный вызов отправки.

Просто убедитесь, что вы сохраняете состояние loading в редуксе и отображаете fallback во время выборки данных.

фрагмент кода

const QuestionSearchContainer = props => {
  ...
  useEffect(() => {
    const {query} = props.match.params
    console.log(query);
    store.dispatch(fetchData(query))
  }, [query]);
  ...
  return <div>      
      {!props.isLoading && <div>My actual question search component with data !</div>}
</div>;
};

export default QuestionSearchContainer;
0 голосов
/ 02 мая 2020

Если вы не хотите выполнять выборку данных с помощью вашего компонента QuestionSearchContainer, вы можете сделать компонент более высокого порядка, чтобы обернуть его тем, что делает выборку ваших данных за вас.

Вы можете легко изменить это HO C, чтобы возвращать обернутый компонент только после завершения загрузки данных. В этой части загрузки предполагается, что fetchData является создателем действия redux thunk . useParams - это хук, экспортированный из реакции-маршрутизатора-dom, который дает вам доступ к параметрам соответствия. useDispatch - это хук, экспортированный из response-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}
    />
  );
};

Другой вариант - создать специальный маршрут, который будет выполнять то, что вы хотите. Например, эта функция OnChangeRoute будет вызывать обратный вызов onChangeParams с текущими параметрами каждый раз, когда параметры изменяются. В этом есть загрузочная опора, которую вы должны передать, так как самому компоненту плевать на то, что вы делаете с параметрами.

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}
        />
      )}
    />
  );
}

В общем, для приставки вы должны использовать диспетчеризацию (или mapDispatchToProps в соединителе HO C), чтобы запустить действие, обновляющее хранилище с вашими данными.

Вот несколько ссылок, которые, как мы надеемся, помогут вам получить контроль над избыточностью.

https://redux.js.org/advanced/async-actions

https://redux-toolkit.js.org/usage/usage-guide#asynchronous -логий c -и выборки данных

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

...