Я использую React Context и хотел бы получить подтверждение моей структуры - PullRequest
1 голос
/ 25 июня 2019

Это мое первое приложение, использующее контекст реагирования с хуками вместо реактив-редукса, и я хотел бы получить справку по структуре приложения. (Я НЕ использую библиотеки реагировать на редуксы или редуксы и саги.)

  • Контекст
const AppContext = createContext({
  client,
  user,
});
  • Пример одного из действий
export const userActions = (state, dispatch) => {
  function getUsers() {
    dispatch({ type: types.GET_USERS });
    axios
      .get("api address")
      .then(function(response) {
        dispatch({ type: types.GOT_USERS, payload: response.data });
      })
      .catch(function(error) {
        // handle error
      });
  }
  return {
    getUsers,
  };
};
  • Reducer (index.js): я использовал код функции combReducer из библиотеки redux
const AppReducer = combineReducers({
  client: clientReducer,
  user: userReducer,
});
  • Root.js
import React, { useContext, useReducer } from "react";
import AppContext from "./context";
import AppReducer from "./reducers";
import { clientActions } from "./actions/clientActions";
import { userActions } from "./actions/userActions";
import App from "./App";

const Root = () => {
  const initialState = useContext(AppContext);
  const [state, dispatch] = useReducer(AppReducer, initialState);
  const clientDispatch = clientActions(state, dispatch);
  const userDispatch = userActions(state, dispatch);

  return (
    <AppContext.Provider
      value={{
        clientState: state.client,
        userState: state.user,
        clientDispatch,
        userDispatch,
      }}
    >
      <App />
    </AppContext.Provider>
  );
};

export default Root;

Итак, всякий раз, когда компонент хочет получить доступ к хранилищу контекста или отправить действие, я делаю это из компонента:

import React, { useContext } from "react";
import ListMenu from "../common/ListMenu";
import List from "./List";
import AppContext from "../../context";
import Frame from "../common/Frame";

const Example = props => {
  const { match, history } = props;
  const { userState, userDispatch } = useContext(AppContext);

  // Push to user detail route /user/userId
  const selectUserList = userId => {
    history.push(`/user/${userId}`);
    userDispatch.clearTabValue(true);
  };

  return (
    <Frame>
      <ListMenu
        dataList={userState.users}
        selectDataList={selectUserList}
      />
      <List />
    </Frame>
  );
};

export default Example;

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

Мне было интересно, как исправить всю эту проблему с повторным рендерингом (если можно по-прежнему использовать мою структуру папок action / reducer).

Кроме того, я извлекаю данные из действия, но я хотел бы отделить это от файла действия, а также от того, как мы работаем над структурой redux-saga. Мне было интересно, если кто-нибудь знает, как отделить это без использования redux / redux-saga.

Спасибо и, пожалуйста, дайте мне знать, если вам нужен код / ​​файл для проверки.

Ответы [ 2 ]

0 голосов
/ 25 июня 2019

Этот эффект (обновление компонентов при обновлении контекста) описан в официальной документации .

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

Возможные решения этой проблемы также описано

Я вижу универсальное решение useMemo

Например

const Example = props => {
    const { match, history } = props;
    const { userState, userDispatch } = useContext(AppContext);

    // Push to user detail route /user/userId
    const selectUserList = userId => {
        history.push(`/user/${userId}`);
        userDispatch.clearTabValue(true);
    };
    const users = userState.users; 

    return useMemo(() => {
        return <Frame>
            <ListMenu
                dataList={users}
                selectDataList={selectUserList}
            />
            <List />
        </Frame>
    }, [users, selectUserList]);  // Here are variables that component depends on
};

Я также могу порекомендовать вам полностью переключиться на Redux.Вы почти там с использованием combineReducers и dispatch.React-redux теперь предоставляет useDispatch и useSelector ловушки , так что вы можете сделать свой код очень близким к тому, что вы делаете сейчас (замените useContext на useSelector и useReducer на useDispatch. Это потребует незначительных изменений в аргументах)

0 голосов
/ 25 июня 2019

Однажды у меня возникла проблема с повторным рендерингом, и я нашел эту информацию на официальном сайте: https://reactjs.org/docs/context.html#caveats Пусть это вам тоже поможет

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...