Наилучшая практика использования React-хуков и Context API для обновления глобального состояния и получения / предоставления данных с нескольких конечных точек - PullRequest
1 голос
/ 31 октября 2019

Я новичок в React hooks / Context API. Я прочитал документацию React Hook / Context, и у меня все еще возникают проблемы со следующим:

  1. Мои попытки обновить глобальное состояние несколькими компонентами-потребителями в настоящее время вызывают частую перезапись состояния контекста из-за перерисовки (например, состояние активности или деталей иногда равно нулю / не определено). Вероятно, поэтому ...
  2. ... Я получаю 400 (неправильный запрос) и / или 500 (сервер) ошибок при случайном обновлении страницы (~ 30% времени загружается контент, как ожидалось,Выдается ~ 70% ошибок. Я полагаю, что это происходит, потому что у нас есть различные состояния контекста, которые вызываются асинхронно).
  3. Я не уверен, как реализовать Отмена Axios, учитывая, что наши useEffect перехватчики вызываютфункции отправки (например, getActivities()) в разные файлы. Примеры, которые я видел, включают выборку данных внутри компонента (а не в контексте).

Я специально ищу помощь для # 1. Мне бы хотелось получить руководство о том, как точно извлекать данные и сохранять их в контексте как глобальное состояние, а затем предоставлять этот контекст дочерним компонентам, позволяя им использовать / обновлять состояние контекста без ненужной перерисовки.

Пыталсяпредоставьте только соответствующие фрагменты кода ниже:

ActivityState.js - должен извлекать данные активности

...
const ActivityState = props => {
  const initialState = {
    activities: [],
    isLoading: false,
    isError: false
  };

  const HEADERS = {
    'Content-Type': 'application/json',
    'user_id': 1
  }

  const [state, dispatch] = useReducer(ActivityReducer, initialState);
  const userContext = useContext(UserContext);

  const getActivities = async () => {
    const { loggedIn } = contactContext;
    let didCancel = false; // attempts to start implementing axios cancellation
    try {
      const res = await axios.get(url);
      dispatch({ type: GET_ACTIVITIES, payload: res.data.data.activities });
    } catch (err) {
      if (!didCancel) {
        dispatch({ type: 'FETCH_FAILURE' });
      }
    }
  }

  const updateActivity = (path, data) => { //update context state
    dispatch({ type: UPDATE_ACTIVITY, payload: { path: path, data: data } });
  };

  const saveActivity = () => { //send new activity data to the backend
    const postData = {
      actions:  [{"293939": []}],
      activities: state.activities
    };
    try {
      const res = axios.post(url,{ data: postData }, { headers: HEADERS });
    } catch (err) {
      console.log(err);
    }
  }

return (
    <ActivityContext.Provider
      value={{
        activities: state.activities,
        data: state.data,
        backup_data: state.backup_data,
        getActivities,
        updateActivity,
        saveActivity,
      }}
    >
      {props.children}
    </ActivityContext.Provider>
  );
};

export default ActivityState;

ActivityReducer.js - переключать операторы, которые будут отправленыby ActivityState.js

...
export default (state, action) => {
  switch (action.type) {
    case GET_ACTIVITIES:
      return {
        ...state,
        activities: action.payload,
        isLoading: true
      };
    case FETCH_FAILURE:
      return {
        ...state,
        isLoading: false,
        isError: true
      };
    case UPDATE_ACTIVITY:
      const { payload: { path }, payload } = action;
      const data = state;
      if (!data.activities)
        return { data };
      const index = data.activities.findIndex(e => e.socium_tracking_number == path.id);
      if(index === -1)
        return { data };
      _.set(data, `activities[${index}].${path.field}`, payload.data);
      return {
        data,
      };
...

DetailsState.js - функции отправки для получения сведений

const DetailsState = props => {

    const initialState = {
        details: null,
    };

    const [state, dispatch] = useReducer(DetailsReducer, initialState);

    const getDetails = async () => {
        try {
            const res = await axios.get(url);
            dispatch({ type: GET_DETAILS, payload: res.data.data[0].details});
        }catch(err) {
            console.log(err)
        }
    };

    return ( 
        <DetailsContext.Provider 
            value={{ details: state.details, getDetails }}
        >
            { props.children }
        </DetailsContext.Provider>
    );
}
export default SchemaState;

DetailsReducer.js - переключательоператор

export default (state, action) => {
    switch (action.type) {
        case GET_DETAILS:
            return {
                ...state,
                details: action.payload,
            };
        default:
            return state;
    }
};

ActivityTable.js - компонент, который потребляет активность Информация

...
const ActivityTable = ({ activity }) => {
  const activityContext = useContext(ActivityContext);
  const { activities, filtered, getActivities } = activityContext;

  const [order, setOrder] = React.useState('asc');
  const [orderBy, setOrderBy] = React.useState(activities.wait_time);

  // Get activity data on mount
  useEffect(() => {
      async function fetchData() {
        await getActivities()
      }
      fetchData();
  }, []);
...

CreateActivity.js - компонент, который потребляет деятельностьи Подробные данные

...
const CreateActivity = props => {
  const activityContext = useContext(ActivityContext);
  const { activities, filtered, getActivities, addActivity } = activityContext;

  const detailsContext = useContext(DetailsContext);
  const { details, getDetails } = detailsContext;

  // Get activity and details data on mount
  useEffect(() => {
     async function fetchData() {
       await getActivities();
       await getSchema();
     }
     fetchData();
  }, []);
...

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

...