React Hook useReducer 总是运行两次 [英] React Hook useReducer always running twice

查看:56
本文介绍了React Hook useReducer 总是运行两次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

function MyComponent(props) {功能减速器(数据,动作){开关(动作.类型){案例初始化":返回 action.payload;案例ADD_NEW":const newData = {...数据};newData.info.push({});返回新数据;}}const [data, dispatch] = React.useReducer(reducer, null);useEffect(() => {获取(网址).then(响应 => {派遣({类型:'初始化',有效载荷:响应});}).catch(错误=> {控制台日志(错误);});}, []);const addNew = () =>{dispatch({ type: 'ADD_NEW' });}返回(<>数据?data.info.length : '没有数据'</>);}

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

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

解决方案

我将如何处理这个问题.它重新运行 action effect 的主要原因是因为你在组件的函数中使用了 reducer.我还继续解决了其他几个问题.

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

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

import React, { useReducer, useState, useEffect } from "react";从react-dom"导入{渲染};从./Hello"导入你好;导入./style.css";const url = `https://picsum.photos/v2/list?page=3&limit=1`;功能应用(道具){const [data, dispatch] = React.useReducer(reducer, null);useEffect(() => {获取(网址).then(异步响应 => {派遣({类型:初始化",有效载荷:(等待 response.json())});}).catch(错误=> {控制台日志(错误);});}, []);const addNew = () =>{dispatch({ type: "ADD_NEW" });};console.log("这里");返回 (<><div>{数据 ?JSON.stringify(data) :还没有数据"}

<button onClick={addNew}>Test</button></>);}render(, document.getElementById("root"));功能减速器(数据,动作){开关(动作.类型){案例初始化":console.log(action.payload, "初始化");返回 action.payload;案例ADD_NEW":const newData = { ...数据};newData.info = newData.info ||[];newData.info.push({});控制台日志(新数据);返回新数据;}}

I am loading data from a public API after my component is mounted. When the data is loaded I am passing it to the reducer, but it always fires twice. This is what I have:

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'</>
   );

}

As you can see the component awaits for the data to populate the reducer, which, when INITIALIZE is also called twice, but I didn't care about it until I needed to call ADD_NEW, because in that case it adds two blank objects into the array instead of only one. I wen't into the documentation for side effects, but I was unable to solve it.

What is the best way to deal with this?

解决方案

Here's how I would deal with the issue. The main reason why it was re-running the action effect was because you had the reducer in the component's function. I also went ahead and fixed several other issues.

The fetch code was a little off due to how fetch works. You have to get the data type off of the response which gives another promise instead of the data directly.

You also needed to make the rendering use {} to indicate that you were using javascript rather than text.

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;
  }
}

这篇关于React Hook useReducer 总是运行两次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆