useReducer с асинхронным действием для выполнения запроса API

#javascript #reactjs

#javascript #reactjs

Вопрос:

У меня есть форма, в которой есть вызываемое поле description , в котором при нажатии вызываемой query кнопки выполняется POST запрос, а затем отправляется текст в поле description в теле запроса.

Я использую useReducer для этого и не уверен, как структурировать действие и эффект использования, когда пользователь нажимает на query кнопку.

Action for querying the data(I am not sure what to return in this case)

 switch (action.type) {
  case "query": {
    return {
      ...state,
    };
  }
}
 

Making the POST request and setting the JSON data in state which is then displayed(Takes as input the data from the field description)

 const fetchData = async (desc) => {
  const response = await fetch("/rank", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ terms: desc }),
  }).catch((e) => console.log(e));
  const dataJSON = await response.json().catch((e) => console.log(e));
  if (response.ok) {
    console.log("OK");
  }
  if (!response.ok) {
    const error = (dataJSON amp;amp; dataJSON.message) || response.status;
    return Promise.reject(error);
  }
  setData(dataJSON.data);
};

useEffect(() => {
  fetchData(description);
}, [description]);
 

Button for making the query

 <Button
  type="button"
  onClick={() => {
    dispatch({ type: "query" });
  }}
>
 

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

Ответ №1:

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

также у вас есть какой-то setData . это приведет к дублированию состояния при использовании useReducer. Я бы посоветовал удалить эти данные state , если вы используете reducer здесь.

Я бы рекомендовал onClick action, чтобы вызвать fetchData и отправить действие при успешном выполнении.

 const fetchData = async () => {
  try {
  const response = await fetch("/rank", {
    method: "POST",
    headers: {
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ terms: description }),
  })
  const dataJSON = await response.json();
  if (response.ok) {
    console.log("OK");
  }
  if (!response.ok) {
    const error = (dataJSON amp;amp; dataJSON.message) || response.status;
    throw error;
  }
  dispatch({ type: "query", data: dataJSON.data });
  } catch (error) {
    console.log(error)
  }
};
 

затем ваш редуктор в вашем редукторе:

 switch (action.type) {
  case "query":
    return {...state, action.data };
  default:
    return state;
}
 

вы также можете добавить некоторые дополнительные действия отправки, например loading , success и error для обработки этих случаев, если это необходимо.

Комментарии:

1. Я получаю сообщение об ошибке {...state, action.data } . В нем говорится unreachable code detected .

2. Спасибо за ваш ответ. Я не вижу, где что находится и что имеет доступ к чему. Как: dispatch({ type: "query", data: dataJSON.data }); получить доступ к редуктору?