2017-02-04 86 views
1

我正在研究基于React.js的大纲(与workflowy类似)。我被困在一个点上。当我按下任何一个项目上的输入时,我想在其下方插入另一个项目。React.js无法在状态更新上重新呈现应用

因此,我已经使用的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:

根据以下建议,如果有人想看看,添加的键= {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} /> 
) 
+1

如果您对代码进行格式化并使其更具可读性,将会更容易。如果可能,您也可以删除任何未使用的代码。 – nem035

+0

单独检查长的不可读代码行: 'const newItems = this.state.items.splice(this.state.items.map((item)=> item._id).indexOf(itemID)+ 1,0,{ _id:(new Date().getTime()),content:'Some Note'})' 'this.setState({items:newItems})' – webdeb

+0

我做了,项目状态对象更新就好了,项目被添加,但该应用程序重新渲染为空 – Hirvesh

回答

1

有多个问题与您的代码:

  1. 在你逝去this.insertItem到子项(不存在)
  2. this.state.items.splice,改变this.state.items,但返回[]。所以,你的新的国家是[]

试试这个:

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

来完成你真正想要的,这是不够的..但至少,当你有固定的,你可以看到一些结果。

+0

谢谢!我相信我在正确的方向。试图让事情正确,将在一些更新:) – Hirvesh

+0

任何想法为什么拼接不工作?我无法理解为什么它在拼接上返回一个空数组... – Hirvesh

+0

哦,我被推迟了。 “splice()”函数不会返回受影响的数组,而是返回已移除元素的数组。如果你什么都不删除,结果数组是空的。 – Hirvesh

3

由于React无法识别您的状态是否改变,因此您错过了在Item上放置一个键。

<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> 
+0

然而,我添加了密钥的状态更新,但它仍然没有重新渲染:/ – Hirvesh

+2

这里不是问题 – webdeb

相关问题