Почему React useReducer возвращает пустое состояние, когда данные присутствуют в первый раз, когда они были получены при использовании useEffect? - PullRequest
0 голосов
/ 06 апреля 2020

Я работаю над простым приложением стека MERN, использующим реагирующие хуки и contextAPI , я выбираю данные из базы данных mongodb с помощью ax ios и устанавливаю переменную массива initialState с useEffect для имитации componentDidMount , тогда initialState используется в качестве параметра для useReducer . Моя проблема в том, что дочерний компонент не получил initialState , но пустой массив, однако все другие реквизиты, такие как disptach и переменные загрузки, проходят. Почему useReducer возвращает пустой массив состояний?

Родительский компонент:

import React, { useEffect, useState, useReducer } from 'react';
import Header from './components/header/Header';
import Main from './components/main/Main';
import AppContext from './context/AppContext';
import axios from 'axios';
import './stylesheets/index.scss';

function App() {
  const [initialState, setInitialState] = useState([]);
  const [isError, setIsError] = useState(false);
  const [isLoading, setIsLoading] = useState(false);

  /* Fetch data */
  const fetchData = async () => {
    setIsError(false);
    setIsLoading(true);
    try {
      const response = await axios.get('/list');
      setInitialState(response.data);
    } catch (error) {
      setIsError(true);
      console.log(`Unable to get: ${error}`);
    }
    setIsLoading(false);
  };

  /* Post new data */
  const postNewData = async (parameter) => {
    setIsError(false);
    try {
      const response = await axios.post('/list', parameter);
      console(response.data);
    } catch (error) {
      setIsError(true);
      console.log(`Unable to post: ${error}`);
    }
  };

  /* Delete data */
  const deleteData = async (id) => {
    setIsError(false);
    try {
      const response = await axios.delete(`/list/${id}`);
      console(response.data);
    } catch (error) {
      setIsError(true);
      console.log(`Unable to delete: ${error}`);
    }
  };

  useEffect(() => {
    /* On load fetch data from the database */
    fetchData();
  }, []);

  useEffect(() => {
    console.log(initialState);
  }, [initialState]); 

  const appReducer = (state = initialState, action) => {
    switch (action.type) {
      case 'ADD_NEW_LIST':
        return postNewData(action.new_list);
      case 'DELETE_LIST':
        return deleteData(action.list_id);
      default:
        return state;
    }
  };

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

  return (
    <AppContext.Provider value={{ state, dispatch, isError, isLoading }}>
      <div className='App'>
        <Header />
        <Main />
      </div>
    </AppContext.Provider>
  );
}

export default App;

Вот дочерний компонент внутри основного компонента:

import React, { useContext, useEffect, useState } from 'react';
import AppContext from '../../context/AppContext';

function Listarea() {
  const { state, isError, isLoading, dispatch } = useContext(AppContext);

    console.log(state);
    console.log(isError);
    console.log(isLoading);

  return <div className='list-area'>list area here</div>;
}

export default Listarea;

А вот консоль .log ouput enter image description here

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

1 Ответ

1 голос
/ 10 апреля 2020

если вы обновите свое значение initialState, оно не изменит состояние вашего useReducer.

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

const appReducer = (state = initialState, action) => {
    switch (action.type) {
      case 'SET_DATA':
        return action.data;
      case 'ADD_NEW_LIST':
        return postNewData(action.new_list);
      case 'DELETE_LIST':
        return deleteData(action.list_id);
      default:
        return state;
    }
  };

const [state, dispatch] = useReducer(appReducer, []);

const fetchData = async () => {
    setIsError(false);
    setIsLoading(true);
    try {
      const response = await axios.get('/list');
      dispatch({ type: 'SET_DATA', data: response.data });
    } catch (error) {
      setIsError(true);
      console.log(`Unable to get: ${error}`);
    }
    setIsLoading(false);
  };
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...