2017-02-04 2 views
1

Я работаю над основанной на React.js outliner (в том же духе, что и 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

Может кто-нибудь помочь мне понять, почему он снова не делает после того, как я уточняю детали?

Edit:

меня обновить код, чтобы добавить ключи, как предложено ниже, по-прежнему делает, как пустой, несмотря на государственную обновление:

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; 

Edit 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 не смог определить, изменилось ли ваше состояние.

<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

Смежные вопросы