3

安装组件后,我正在从公共 API 加载数据。加载数据时,我将其传递给减速器,但它总是触发两次。这就是我所拥有的:

function MyComponent(props) {
   function reducer(data, action) {
      switch (action.type) {
         case 'INITIALIZE':
            return action.payload;
         case 'ADD_NEW':
            const newData = {...data};
            newData.info.push({});
            return newData;
      }
   }

   const [data, dispatch] = React.useReducer(reducer, null);

   useEffect(() => {
      fetch(URL)
        .then(response => {
            dispatch({
               type: 'INITIALIZE',
               payload: response
            });
         })
        .catch(error => {
            console.log(error);
         });
   }, []);

   const addNew = () => {
      dispatch({ type: 'ADD_NEW' });
   }

   return(
       <>data ? data.info.length : 'No Data Yet'</>
   );

}

如您所见,该组件等待数据填充减速器,该减速器何时INITIALIZE也被调用两次,但在需要调用之前我并不关心它ADD_NEW,因为在这种情况下,它会将两个空白对象添加到数组中只有一个。我没有进入有关副作用的文档,但我无法解决它。

处理这个问题的最佳方法是什么?

4

1 回答 1

3

以下是我将如何处理这个问题。它重新运行动作效果的主要原因是因为您在组件的功能中有减速器。我还继续解决了其他几个问题。

由于 fetch 的工作方式,fetch 代码有点偏离。您必须从响应中获取数据类型,这会给出另一个承诺,而不是直接提供数据。

您还需要使渲染使用 {} 来表明您使用的是 javascript 而不是文本。

import React, { useReducer, useState, useEffect } from "react";
import { render } from "react-dom";
import Hello from "./Hello";
import "./style.css";
const url = `https://picsum.photos/v2/list?page=3&limit=1`;
function App(props) {
  const [data, dispatch] = React.useReducer(reducer, null);

  useEffect(() => {
    fetch(url)
      .then(async response => {
        dispatch({
          type: "INITIALIZE",
          payload: (await response.json())
        });
      })
      .catch(error => {
        console.log(error);
      });
  }, []);

  const addNew = () => {
    dispatch({ type: "ADD_NEW" });
  };
  console.log("here");
  return (
    <>
      <div>{data ? JSON.stringify(data) : "No Data Yet"}</div>
      <button onClick={addNew}>Test</button>
    </>
  );
}

render(<App />, document.getElementById("root"));
function reducer(data, action) {
  switch (action.type) {
    case "INITIALIZE":
      console.log(action.payload, "Initialize");
      return action.payload;
    case "ADD_NEW":
      const newData = { ...data };
      newData.info = newData.info || [];
      newData.info.push({});
      console.log(newData);
      return newData;
  }
}
于 2020-04-07T01:29:06.057 回答