Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/375.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/reactjs/22.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript ReactJS-无限循环调用包装方法_Javascript_Reactjs - Fatal编程技术网

Javascript ReactJS-无限循环调用包装方法

Javascript ReactJS-无限循环调用包装方法,javascript,reactjs,Javascript,Reactjs,我有无限循环的常见问题,我不知道为什么 Im使用reactJS 16.5.2 循环通常发生在您在不允许的位置写入SetState时(例如在render方法中) 我遵循这个指南: 关注这个问题 我制作了几个HOC(Decorators/Wrapper)组件,将通用方法集中在一个点上,使用道具将它们传播给每个孩子 它通常工作得很好 我试图简化下面的组件结构 问题在于形式及其子对象。 其中一个输入有一个下拉列表,必须用上包装器的方法填充该下拉列表。我将调用放入componentDidMount(如上面

我有无限循环的常见问题,我不知道为什么

Im使用reactJS 16.5.2

循环通常发生在您在不允许的位置写入SetState时(例如在render方法中)

我遵循这个指南: 关注这个问题

我制作了几个HOC(Decorators/Wrapper)组件,将通用方法集中在一个点上,使用道具将它们传播给每个孩子

它通常工作得很好

我试图简化下面的组件结构

问题在于形式及其子对象。 其中一个输入有一个下拉列表,必须用上包装器的方法填充该下拉列表。我将调用放入componentDidMount(如上面的链接所示)。不幸的是,包装器setState似乎触发了表单组件的完整描述和重新构建。从包装到表单,我在每个构造函数中都放了一个console.log。只有表单及其所有输入被重新创建(而不是更新)

由于ComponentDidMount每次都会被触发,因此这种重新创建会生成一个无限循环

我不知道怎么解决这个问题。我检查了每个“键”属性,所有组件都有其唯一的键。我在问你为什么要重新创建而不是更新

是由于父渲染中的表单构建方法造成的吗?如果是这样的话,哪种设计模式适合构建具有异步数据填充的表单


简化您的生活,只需创建一个功能相同的
容器组件,而不是创建一堆包装器。例如,您可以创建一个关心
数据
状态
容器
,然后与可重用子组件
共享该容器及其方法(如下所示,两者的功能相同)

这与从API获取数据的方式完全相同。您将在
componentDidMount
中检索数据,将其设置为
状态
,然后将
状态
传递给可重用组件

您可以使用可重用组件获得超粒度。例如,一个可重复使用的按钮,其唯一目的是提交表单。或者一个只捕获1到100之间的数字的可重用输入,以此类推

如果您的组件是嵌套的,那么考虑使用.< /P> 工作示例:

容器/Form.js(容器组件)

import React,{Component}来自“React”;
从“./组件/字段”导入字段;
导出默认类表单扩展组件{
状态={
按钮区:[
{id:“苹果”,数量:1},
{id:“草莓”,数量:1},
{id:“葡萄”,数量:1},
{id:“杏子”,数量:1}
]
};
把手按钮点击=id=>{
this.setState(prevState=>({
buttonFields:prevState.buttonFields.map(
项目=>
id==item.id?{id,数量:item.quantity+1}:{…item}
)
}));
};
渲染=()=>(
);
}
组件/Fields.js(可重用组件)

从“React”导入React;
导出默认值({buttonFields,onButtonClick,title})=>(
{title}
{buttonFields.map({id,quantity})=>(
onButtonClick(id)}
>
{id}({quantity})
))}
);
容器/Wrapper.js(不必要的包装)

import React,{Component}来自“React”;
导出默认WrappedComponent=>{
类形式扩展组件{
状态={
按钮区:[
{id:“苹果”,数量:1},
{id:“草莓”,数量:1},
{id:“葡萄”,数量:1},
{id:“杏子”,数量:1}
]
};
把手按钮点击=id=>{
this.setState(prevState=>({
buttonFields:prevState.buttonFields.map(
项目=>
id==item.id?{id,数量:item.quantity+1}:{…item}
)
}));
};
渲染=()=>(
);
}
申报表;
};

简化您的生活,而不是创建一堆包装,只需创建一个功能相同的
容器组件即可。例如,您可以创建一个关心
数据
状态
容器
,然后与可重用子组件
共享该容器及其方法(如下所示,两者的功能相同)

这与从API获取数据的方式完全相同。您将在
componentDidMount
中检索数据,将其设置为
状态
,然后将
状态
传递给可重用组件

您可以使用可重用组件获得超粒度。例如,一个可重复使用的按钮,其唯一目的是提交表单。或者一个只捕获1到100之间的数字的可重用输入,以此类推

如果您的组件是嵌套的,那么考虑使用.< /P> 工作示例:

容器/Form.js(容器组件)

import React,{Component}来自“React”;
从“./组件/字段”导入字段;
导出默认类表单扩展组件{
状态={
按钮区:[
{id:“苹果”,数量:1},
{id:“草莓”,数量:1},
{id:“葡萄”,数量:1},
{id:“杏子”,数量:1}
]
};
把手按钮点击=id=>{
this.setState(prevState=>({
buttonFields:prevState.buttonFields.map(
项目=>
id==item.id?{id,数量:item.quantity+1}:{…item}
)
}));
};
渲染=()=>(
);
}
组件/Fields.js(可重用组件)

从“React”导入React;
导出默认值({buttonFields,onButtonClick,title})=>(
{title}
{buttonFields.map({id,quantity})=>(
onButtonClick(id)}
>
{id}({quantity})
))}
);
容器/Wrapper.js(不必要
import React, { Component } from "react";
import Fields from "../components/Fields";

export default class Form extends Component {
  state = {
    buttonFields: [
      { id: "Apples", quantity: 1 },
      { id: "Strawberries", quantity: 1 },
      { id: "Grapes", quantity: 1 },
      { id: "Apricots", quantity: 1 }
    ]
  };

  handleButtonClick = id => {
    this.setState(prevState => ({
      buttonFields: prevState.buttonFields.map(
        item =>
          id === item.id ? { id, quantity: item.quantity + 1 } : { ...item }
      )
    }));
  };

  render = () => (
    <Fields
      {...this.state}
      onButtonClick={this.handleButtonClick}
      title="Container Component"
    />
  );
}
import React from "react";

export default ({ buttonFields, onButtonClick, title }) => (
  <div className="container">
    <h1 style={{ textAlign: "center" }}>{title}</h1>
    {buttonFields.map(({ id, quantity }) => (
      <button
        style={{ marginRight: 10 }}
        className="uk-button uk-button-primary"
        key={id}
        onClick={() => onButtonClick(id)}
      >
        {id} ({quantity})
      </button>
    ))}
  </div>
);
import React, { Component } from "react";

export default WrappedComponent => {
  class Form extends Component {
    state = {
      buttonFields: [
        { id: "Apples", quantity: 1 },
        { id: "Strawberries", quantity: 1 },
        { id: "Grapes", quantity: 1 },
        { id: "Apricots", quantity: 1 }
      ]
    };

    handleButtonClick = id => {
      this.setState(prevState => ({
        buttonFields: prevState.buttonFields.map(
          item =>
            id === item.id ? { id, quantity: item.quantity + 1 } : { ...item }
        )
      }));
    };

    render = () => (
      <WrappedComponent
        {...this.state}
        onButtonClick={this.handleButtonClick}
        title="Wrapper"
      />
    );
  }

  return Form;
};
renderForm()
{
  var WrappedFormComponent = FormHOC(SomeFormComponent();
  return <WrappedFormComponent {...this.props} [...] />
}
const WrappedFormComponent = FormHOC(SomeFormComponent();
export default class FinalComponent extends React.Component