简体   繁体   English

React:如何设置对象属性的状态?

[英]React: How to set state of object property?

I am a beginner with React and I have been using the NPM package react- tabs in order to display tabs on my site. 我是React的初学者,并且一直在使用NPM软件包的react-tabs以便在我的网站上显示标签。

I have been trying to allow the user to update descriptions of their profiles using a checkbox to open an input type=text tag allowing the user to put in their own details for their profile. 我一直在尝试允许用户使用复选框打开输入type = text标签来更新其个人资料的描述,从而允许用户输入自己的个人资料作为个人资料。

However, I am struggling to set the state of the description for the tab using the handleDesc function. 但是,我正在努力使用handleDesc函数设置选项卡的描述状态。 I am not sure how I can update the state of the descriptions for each tab. 我不确定如何更新每个选项卡的描述状态。 I keep getting the error "A component is changing a controlled input of type checkbox to be uncontrolled." 我不断收到错误消息“组件正在将复选框的受控输入更改为不受控制”。

Can anyone help me? 谁能帮我?

class EditSite extends React.Component {
constructor(props) {
    super(props);
    this.state = {About: true,
        "Opening Hours": true,
        Contact: true,
        Menu: false,
        Offers: false,
        "External Links": true,
        tabOptions: {
            About: {desc:'1'},
            "Opening Hours": {desc: '2'},
            Contact: {desc:'3'},
            Menu: {desc:'4'},
            Offers: {desc:'5'},
            "External Links": {desc:'6'},
            }
        }

Below is the function (handleDesc) I am struggling with to set the state of the descriptions. 下面是我正在努力设置描述状态的函数(handleDesc)。

handleDesc = (event) => {
    let tabOptions = {...this.state.tabOptions[event.target.name]};
    tabOptions = event.target.value;
    console.log(tabOptions);
    this.setState({tabOptions: [event.target.name]});
}   

 render() {
    const links = [];
    const tabs = [];
    const tabPanels = [];

The second input tag is where I would like the user to be able to add their own details to the specific tab. 我希望用户在第二个输入标签中将自己的详细信息添加到特定选项卡。

Object.keys(this.state.tabOptions).forEach(name => {
  links.push(
      <div>
      <label key={name}>{name}</label>
      <input
        type="checkbox"
        checked={this.state[name]}
        name={name}
        onChange={this.handleCheckClicked}
      />
      { this.state[name] === true ? (
      <input
      name={name}
      type='text'
      onChange={this.handleDesc}
      />
      ) : null }
      </div>
  );

  if (!this.state[name]) return;

  const { desc } = this.state.tabOptions[name];

  tabs.push(
    <Tab>
      <h3>{name}</h3>
    </Tab>
  );

  tabPanels.push(
    <TabPanel> 
        {desc}
    </TabPanel>
  );
});

A quick way to resolve this would be to revise that code that binds the <input /> element's onChange handler to the following: 解决此问题的快速方法是修改将<input />元素的onChange处理程序绑定到以下代码:

links.push(
      <div>
      <label key={name}>{name}</label>
      <input
        type="checkbox"
        checked={this.state[name]}
        name={name}
        onChange={ (event) => this.handleCheckClicked(event) /* <-- update this also */ }
      />
      { this.state[name] === true ? (
      <input
      name={name}
      type='text'
      onChange={ (event) => this.handleDesc(event) /* [ UPDATE HERE ] */ } 
      />
      ) : null }
      </div>
  );

By declaring an arrow function inline like this: 通过这样声明一个内联箭头功能:

onChange={ (event) => this.handleDesc(event) }

it will set the context of the handleDesc function to be the <EditSite /> component (currently, the context will be the global window object). 它将handleDesc函数的上下文设置为<EditSite />组件(当前,上下文将是全局window对象)。 This means that when you access this.state , or call a method like this.setState() inside of the handleDesc , it will work as expected. 这意味着,当您访问this.state或在handleDesc内调用类似this.setState()的方法时,它将按预期工作。

For more information on this subtle characteristic of "arrow functions" see this article . 有关“箭头功能”的微妙特征的更多信息, 请参见本文

Update 更新

Also, consider updating your handleDesc method like so to correctly mutate your state: 此外,考虑像这样更新handleDesc方法以正确改变状态:

handleDesc = (event) => {
    let tabOptions = {...this.state.tabOptions[event.target.name]};
    tabOptions = event.target.value;
    console.log(tabOptions);
    this.setState({tabOptions}); // <--- Update this line
}  

Update 2 更新2

On further investigation (into react's source code), it would see the problem is that your <input /> element does not have a checked attribute when this.state[name] === true is satisfied. 在进一步研究(放入React的源代码)中,它会看到问题在于,当this.state[name] === true时,您的<input />元素没有checked属性。 If you apply a dummy attribute/value pair of checked={ true } on the input rendered in the this.state[name] === true case, this warning message should stop showing: 如果在this.state[name] === true情况下呈现的输入上应用一个checked={ true }的虚拟属性/值对,则此警告消息应停止显示:

links.push(
  <div>
  <label key={name}>{name}</label>
  <input
    type="checkbox"
    checked={this.state[name]}
    name={name}
    onChange={this.handleCheckClicked}
  />
  { this.state[name] === true ? (
  <input
  name={name}
  type='text'
  checked={ true } /* <-- Update this line, don't include this comment in code */
  onChange={this.handleDesc}
  />
  ) : null }
  </div>
 );

SetState wants a new object. SetState需要一个新对象。 So settings just a property of a nested object isn't possible in that way. 因此,无法通过这种方式仅设置嵌套对象的属性。 What you could do is copying the tabOptions and changing the properties you want before you pass it to setState. 您可以做的就是复制tabOptions并更改所需的属性,然后再将其传递给setState。

example

handleDesc = (event) => {

const newTabOptions = {
  ...this.state.tabOptions,
  [event.target.name]: {desc: event.target.value}

this.setState({tabOptions: newTabOptions});
}   

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM