React - использование функции обратного вызова с useState Hook - PullRequest
0 голосов
/ 07 мая 2020

Мне нужно использовать функцию обратного вызова сразу после обновления обработчика состояния.

Перед обработчиками я мог бы сделать это очень простым способом, следующим образом:

myFunction= () => {
    this.setState({
        something: "something"
    }, () => {
     // do something with this.state
    })
}

Вот мой код:

const EmployeeDetails = () => 
const [state, setState] = useState({
    employee: undefined,
    companyDocuments: undefined,
    personalDocuments: undefined,
});

useEffect(() => {
    const fetchData = async () => {
        axios
            .all([
                await axios.get("someUrl"),
                await axios.get("someUrl"),
                await axios.get("someUrl"),
            ])
            .then(
                axios.spread((...responses) => {
                    setState({
                        employee: responses[0].data,
                        companyDocuments: responses[1].data,
                        personalDocuments: responses[2].data,
                    });
                })
            )
            .catch(errors => {});
    };
    fetchData()
    .then(processMyEmployee); // should be called something like this
}, []);

const processMyEmployee= () => {
  // crash because state.employee is not fetched yet
}

return (
    <div>it works!</div>
);
};

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

Ответы [ 3 ]

2 голосов
/ 07 мая 2020

Чтобы выполнить блок поста кода, обновление состояния завершено, вы используете хук useEffect с state в качестве зависимости и отключаете его выполнение при начальном рендеринге

const initialRender = useRef(true);
useEffect(() => {
   if(!initialRender.current) {
     processMyEmployee()
   } else {
      initialRender.current = false;
   }
}, [state]);

useEffect(() => {
    const fetchData = async () => {
        axios
            .all([
                await axios.get("someUrl"),
                await axios.get("someUrl"),
                await axios.get("someUrl"),
            ])
            .then(
                axios.spread((...responses) => {
                    setState({
                        employee: responses[0].data,
                        companyDocuments: responses[1].data,
                        personalDocuments: responses[2].data,
                    });
                })
            )
            .catch(errors => {});
    };
    fetchData()
}, []);

const processMyEmployee= () => {
  //processing here
}
2 голосов
/ 07 мая 2020
• 1000 этот слушатель, он будет запускаться при изменении этой переменной.

Если ошибка не исчезнет, ​​добавьте логический переключатель к вашей функции:

fetchData()
.then(resp=>processMyEmployee(resp)); 
}, [employee]);

const processMyEmployee= (resp) => {
    if(resp){
        //* do something
    }
  }
1 голос
/ 07 мая 2020

Ваш код в основном правильный, и дело только в размещении.

Можете ли вы попробовать следующий код и сообщить мне, поможет ли это!

const initialState = {
  employee: undefined,
  companyDocuments: undefined,
  personalDocuments: undefined,
};

const EmployeeDetails = () => {
  const [state, setState] = useState(initialState);

  useEffect(() => {
    const fetchData = async () => {
      axios
        .all([await axios.get('someUrl'), await axios.get('someUrl'), await axios.get('someUrl')])
        .then(
          axios.spread((...responses) => {
            setState({
              employee: responses[0].data,
              companyDocuments: responses[1].data,
              personalDocuments: responses[2].data,
            });
          }),
        )
        .catch(errors => {});
    };


    if (state.employee) {
      processMyEmployee();
    } else {
      // This is to ensure that the call doesn't go in infinite loop
      // Currently my suggestion is strictly using `state.employee` but 
      // you should change it based on your requirement
      fetchData();
    }
  }, [state]);

  const processMyEmployee = () => {
    const { employee } = state;
    const employeeInfo = Object.values(employee);
    employeeInfo.forEach(value => {
      // code goes here
    });
  };

  return <div>it works!</div>;
};
...