2016-10-23 2 views
0

Ich habe eine einfache Todolist Struktur in den Zustand der Komponente. Dies ist ein Array mit zwei Feldern namens 'content' und einem 'done'. Ich fange Klicken Reihe Artikel mit einem einfachen onClick() Funktion von den Eltern auf TodoItem Childs übergeben (wie Tutorial vorschlagen Reagieren):Wie kann ich den Wert eines Elements in Array ändern, ohne andere in React ändern

render() { 
    const tthis = this; 

    var myList = tthis.state.todos.map(function(todo,index){ 

     var myOnCLick = function(){ 
     var newTodo = {content: todo.content, done: !todo.done}; 
     tthis.state.todos[index] = newTodo; 
     tthis.setState({}); 

     } 
     return <Todo key={index} todo={todo} onClick={myOnCLick}/> 
    }) 

    return (
    <ul className="list"> 
     { myList } 
    </ul> 
    ) 
} 

Dieser Code funktioniert ohne Probleme, aber ich weiß nicht so gut gefällt. Ich würde eine gute Lösung finden, um den Wert eines einzelnen Elements in einem Array zu ändern. Ich fand, dass in Unveränderlichkeit Helfer von React DOC:

{$ Satz: any} das Ziel vollständig ersetzen.

Und in einer guten Antwort in diesem Forum habe ich ein Beispiel:

this.setState({ 
    todos: update(this.state.todos, {1: {done: {$set: true}}}) 

Aber ich kann 1 nicht in meinem Fall verwenden. Ich habe Index, der mir den Index der angeklickt Todo in todos Liste gibt.

Antwort

1

Sie können den Wert der done Eigenschaft auf dem einzelnen todo Objekt spiegeln das Array in der folgenden Art und Weise aufgeführt in:

flipDone(id) { 
    let index = Number(id); 

    this.setState({ 
    todos: [ 
     ...this.state.todos.slice(0, index), 
     Object.assign({}, this.state.todos[index], {done: !this.state.todos[index].done}), 
     ...this.state.todos.slice(index + 1) 
    ] 
    }); 
} 

Hier ist eine Demo: http://codepen.io/PiotrBerebecki/pen/jrdwzB

Voll Code:

class TodoList extends React.Component { 
    constructor() { 
    super(); 
    this.flipDone = this.flipDone.bind(this); 
    this.state = { 
     todos: [ 
     {content: 'Go shopping', done: false}, 
     {content: 'Walk the dog', done: false}, 
     {content: 'Wash the dishes', done: false}, 
     {content: 'Learn React', done: false} 
     ] 
    }; 
    } 

    flipDone(id) { 
    let index = Number(id); 

    this.setState({ 
     todos: [ 
     ...this.state.todos.slice(0, index), 
     Object.assign({}, this.state.todos[index], {done: !this.state.todos[index].done}), 
     ...this.state.todos.slice(index + 1) 
     ] 
    }); 
    } 

    render() { 
    const myList = this.state.todos.map((todo, index) => { 
     return (
     <Todo key={index} 
       clickHandler={this.flipDone} 
       content={todo.content} 
       done={todo.done} 
       id={index} 
     /> 
    ); 
    }) 

    return (
     <ul className="list"> 
     {myList} 
     </ul> 
    ); 
    } 
} 


class Todo extends React.Component { 
    constructor() { 
    super(); 
    this.handleClick = this.handleClick.bind(this); 
    } 

    handleClick(event) { 
    this.props.clickHandler(event.target.id); 
    } 

    render() { 
    return (
     <li> 
     <button onClick={this.handleClick} 
       id={this.props.id}> 
      Click me 
     </button> --- 
     {String(this.props.done)} --- 
     {this.props.content}  
     </li> 
    ); 
    } 
} 


ReactDOM.render(
    <TodoList />, 
    document.getElementById('app') 
); 
+0

Möchten Sie, dass ich etwas zu dem oben genannten hinzufüge, oder beantwortet es Ihre Frage? –

+0

Ich habe nie eine Dreipunktsyntax verwendet. Ihre Lösung funktioniert großartig, aber alle li im Listenaufruf werden jedes Mal gerendert :) – user3528466

+0

Die 3-Punkt-Syntax wird als Spread-Operator bezeichnet. Zum Beispiel: 'let cold = ['Herbst', 'Winter']; '' laß warm = ['Frühling', 'Sommer']; '' console.log ([... kalt, ... warm])) '=>' ['Herbst', 'Winter', 'Frühling', 'Sommer'] 'Weitere Informationen finden Sie hier: https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Spread_operator –

Verwandte Themen