通过更改状态数组中的整个对象来更新状态

时间:2017-02-25 17:14:38

标签: reactjs state

我正在尝试创建更新应用程序状态的输入行。该应用程序目前只有两个组件,TimeCalc和ItemsList。 State存储在TimeCalc中,ItemsList处理条件渲染(显示状态或显示输入行。

我已设法获取已编辑和更新的对象,但我正在努力用正确的状态对象替换更新的对象。对象包含道具_id,title,start和end,最好是我想搜索匹配的_id,并替换状态中的整个对象。但是看到_id道具是其他道具的兄弟支柱,我不知道该怎么做。

这是TimeCalc:

import React from 'react';
import ItemsList from '../components/ItemsList';
const items = [
 {
    _id: '112233',
    title: 'M1',
    start: 900,
    end: 1800
  },
  {
    _id: '223344',
    title: 'M2',
    start: 1000,
    end: 1900
  }
];
export default class TimeCalc extends React.Component {
  state = {
    items
  }
  handleUpdate = (update) => {

  }
  render = () => {
    return (
      <div class="timeCalc flex center">
        <ItemsList items={this.state.items} handleUpdate={this.handleUpdate}/>
      </div>
    )
  }
}

这是ItemsList:

import React from 'react';
export default class ItemsList extends React.Component {
  state = {
    editing: null
  }
  toggleEditing = (itemId) => {
    this.setState({
      editing: itemId
    })
  }
  handleEditItem = () => {
    let itemId = this.state.editing;
    this.handleItemsUpdate({
      _id: itemId,
      title: this.refs[`title_${itemId}`].value,
      start: this.refs[`start_${itemId}`].value,
      end: this.refs[`end_${itemId}`].value,
    })
  }
  handleItemsUpdate = (update) => {
    console.log(update);
    this.props.handleUpdate(update);
    this.setState( { editing: null } );
  }
  renderItemOrEditField = (item) => {
    if(this.state.editing === item._id) {
      return <li key={`editing-${item._id} `} class="list-item flex row">
        <input
          onKeyDown={this.handleEditField}
          type="text"
          class="form-input"
          ref={`title_${item._id}`}
          name="title"
          defaultValue={item.title}
          />
        <input
          onKeyDown={this.handleEditField}
          type="text"
          class="form-input"
          ref={`start_${item._id}`}
          name="start"
          defaultValue={item.start}
          />
        <input
          onKeyDown={this.handleEditField}
          type="text"
          class="form-input"
          ref={`end_${item._id}`}
          name="end"
          defaultValue={item.end}
          />
          <button onClick={this.handleEditItem} label="Update Item"/>
        </li>
    } else {
      return <li
        onClick = {this.toggleEditing.bind(null, item._id)}
        key = {item._id}
        class = "list-position">
        {` ${item.title} & ${item.start} && ${item.end} && ${item._id}`}
        </li>
    }
  }
  render = () => {
    return (
      <ul class="itemsList">
        {this.props.items.map((item) => {
          return this.renderItemOrEditField(item);
        })}
    </ul>
    )
  }
}

我试图在React&#34;中重新创建MeteorChef&#34;点击编辑字段,但他以流星方式存储状态。

1 个答案:

答案 0 :(得分:0)

我建议您将所有状态移动到父组件。保持ItemsList无状态可以更清晰地区分您的问题并使代码更容易理解。在这种情况下,需要关注的所有ItemsList都是根据存储在父级中的状态来呈现数据。在TimeCalc组件中,向状态对象添加“编辑”键,并添加一个方法来处理ItemsList中的更新:

state = {
  items,
  editing: null,
}

handleUpdate = (editing) => {
  this.setState({ editing });
}

然后在渲染子组件时,将此处理函数,items数组和“编辑”键作为props传递:

<ItemsList items={this.state.items} editing={this.state.editing} handleUpdate={this.handleUpdate}/>

现在,ItemsList可以成为无状态功能组件,如下所示:

import React from 'react';

const renderItemOrEditField = (item, editing, handleUpdate) => (
  {editing === item._id ? (
    <li key={item._id} className="list-item flex row">
      <input onKeyDown={handleUpdate(item._id}
      // The rest of your content to render if item is being edited
  ) : (
    // content to be rendered if item isn't being edited goes here
  )}
);

export default const ItemsList = (props) => (
  <ul className="itemsList">
    {props.items.map((item) => {
      return renderItemOrEditField(item, props.editing, props.handleUpdate);
    })}
  </ul>
);

这种使用“智能”容器组件管理状态和业务逻辑以及“哑”表示组件的策略可以大大有助于保持应用程序的可维护性和脆弱性。希望这有帮助!