React.js无法在状态更新

时间:2017-02-04 09:20:10

标签: javascript reactjs ecmascript-6

我正在研究基于React.js的大纲(与工作流程类似)。我陷入了困境。当我在任何一个项目上按Enter键时,我想在它下面插入另一个项目。

所以我使用setState函数在当前项目的正下方插入一个项目,如下面的代码片段所示:

 this.setState({
      items: this.state.items.splice(this.state.items.map((item) => item._id).indexOf(itemID) + 1, 0, {_id: (new Date().getTime()), content: 'Some Note'})
 })

但是,该应用程序将重新呈现为空白而不会显示任何错误。

到目前为止我的完整资料来源:

import './App.css';

import React, { Component } from 'react';
import ContentEditable from 'react-contenteditable';

const items = [
  {
    _id: 0,
    content: 'Item 1 something',
    note: 'Some note for item 1'
  },
  {
    _id: 5,
    content: 'Item 1.1 something',
    note: 'Some note for item 1.1'
  },
  {
    _id: 1,
    content: 'Item 2 something',
    note: 'Some note for item 2',
    subItems: [
      {
        _id: 2,
        content: 'Sub Item 1 something',
        subItems: [{
          _id: 3,
          content: 'Sub Sub Item 4'
        }]
      }
    ]
  }
];

class App extends Component {
  render() {
    return (
      <div className="App">
        <Page items={items} />
      </div>
    );
  }
}

class Page extends Component {
  constructor(props) {
    super(props);

    this.state = {
      items: this.props.items
    };

    this.insertItem = this.insertItem.bind(this);
  }

  render() {
    return (
      <div className="page">
        {
          this.state.items.map(item =>
            <Item _id={item._id} content={item.content} note={item.note} subItems={item.subItems} insertItem={this.insertItem} />
          )
        }
      </div>
    );
  }

  insertItem(itemID) {
    console.log(this.state.items);

    this.setState({
      items: this.state.items.splice(this.state.items.map((item) => item._id).indexOf(itemID) + 1, 0, {_id: (new Date().getTime()), content: 'Some Note'})
    })

    console.log(this.state.items);
  }
}

class Item extends Component {
  constructor(props) {
    super(props);

    this.state = {
      content: this.props.content,
      note: this.props.note
    };

    this.saveItem = this.saveItem.bind(this);
    this.handleKeyPress = this.handleKeyPress.bind(this);
  }

  render() {
    return (
      <div key={this.props._id} className="item">
        <ContentEditable html={this.state.content} disabled={false} onChange={this.saveItem} onKeyPress={(event) => this.handleKeyPress(this.props._id, event)} />

        <div className="note">{this.state.note}</div>
        {
          this.props.subItems &&
          this.props.subItems.map(item =>
            <Item _id={item._id} content={item.content} note={item.note} subItems={item.subItems} insertItem={this.insertItem} />
          )
        }
      </div>
    );
  }

  saveItem(event) {
    this.setState({
      content: event.target.value
    });
  }

  handleKeyPress(itemID, event) {
    if (event.key === 'Enter') {
      event.preventDefault();
      console.log(itemID);
      console.log(event.key);
      this.props.insertItem(itemID);
    }
  }
}

export default App;

github回购:https://github.com/Hirvesh/mneme

任何人都可以帮我理解为什么在我更新项目后它没有再次渲染?

修改

我已更新代码以添加密钥,如下所示,尽管状态更新仍然呈现为空白:

import './App.css';

import React, { Component } from 'react';
import ContentEditable from 'react-contenteditable';

const items = [
  {
    _id: 0,
    content: 'Item 1 something',
    note: 'Some note for item 1'
  },
  {
    _id: 5,
    content: 'Item 1.1 something',
    note: 'Some note for item 1.1'
  },
  {
    _id: 1,
    content: 'Item 2 something',
    note: 'Some note for item 2',
    subItems: [
      {
        _id: 2,
        content: 'Sub Item 1 something',
        subItems: [{
          _id: 3,
          content: 'Sub Sub Item 4'
        }]
      }
    ]
  }
];

class App extends Component {
  render() {
    return (
      <div className="App">
        <Page items={items} />
      </div>
    );
  }
}

class Page extends Component {
  constructor(props) {
    super(props);

    this.state = {
      items: this.props.items
    };

    this.insertItem = this.insertItem.bind(this);
  }

  render() {
    return (
      <div className="page">
        {
          this.state.items.map(item =>
            <Item _id={item._id} key={item._id} content={item.content} note={item.note} subItems={item.subItems} insertItem={this.insertItem} />
          )
        }
      </div>
    );
  }

  insertItem(itemID) {
    console.log(this.state.items);

    this.setState({
      items: this.state.items.splice(this.state.items.map((item) => item._id).indexOf(itemID) + 1, 0, {_id: (new Date().getTime()), content: 'Some Note'})
    })

    console.log(this.state.items);
  }
}

class Item extends Component {
  constructor(props) {
    super(props);

    this.state = {
      content: this.props.content,
      note: this.props.note
    };

    this.saveItem = this.saveItem.bind(this);
    this.handleKeyPress = this.handleKeyPress.bind(this);
  }

  render() {
    return (
      <div className="item">
        <ContentEditable html={this.state.content} disabled={false} onChange={this.saveItem} onKeyPress={(event) => this.handleKeyPress(this.props._id, event)} />

        <div className="note">{this.state.note}</div>
        {
          this.props.subItems &&
          this.props.subItems.map(item =>
            <Item _id={item._id} key={item._id} content={item.content} note={item.note} subItems={item.subItems} insertItem={this.insertItem} />
          )
        }
      </div>
    );
  }

  saveItem(event) {
    this.setState({
      content: event.target.value
    });
  }

  handleKeyPress(itemID, event) {
    if (event.key === 'Enter') {
      event.preventDefault();
      console.log(itemID);
      console.log(event.key);
      this.props.insertItem(itemID);
    }
  }
}

export default App;

编辑2:

根据以下建议,添加了key = {i._id},仍然无法正常工作,如果有人想看看,请将最新代码推送到github。

  this.state.items.map((item, i) =>
    <Item _id={item._id} key={i._id} content={item.content} note={item.note} subItems={item.subItems} insertItem={this.insertItem} />
  )

2 个答案:

答案 0 :(得分:3)

您错过了将一个键放在Item上,因为React无法识别您的状态是否发生变化。

<div className="page">
{
  this.state.items.map((item, i) =>
     <Item _id={item._id} 
      key={i} // <---- HERE!!
      content={item.content} 
      note={item.note} 
      subItems={item.subItems} 
      insertItem={this.insertItem} />     
  )}
</div>

答案 1 :(得分:1)

您的代码存在多个问题:

    您正在将this.insertItem传递给SubItems(不存在)
  1. 您的this.state.items.splice,更改this.state.items,但返回[]。所以你的新州是[]
  2. 试试这个:

    this.state.items.splice(/* your splice argument here */)
    this.setState({ items: this.state.items }, () => {
      // this.setState is async! so this is the proper way to check it.
      console.log(this.state.items);
    });
    

    要完成你真正想要的东西,这还不够......但至少,当你修复它时,你可以看到一些结果。