2017-05-26 51 views
1

嘿,我正在尝试创建一个简单的待办事项列表,并添加了必要的组件。但是,状态不会在标题{this.state.data.length}和TodoList {this.state.data}中更新。一个Codepen和相关的代码如下。在组件中没有更新的状态

https://codepen.io/skasliwal12/pen/BREYXK

const TodoForm = ({addTodo}) => { 
    let input; 
    return (
    <div> 
    <input ref={node => {input = node;}} /> 
    <button onClick={(e) => { 
     e.preventDefault(); 
     addTodo(input.value); 
     input.value=''; 
    }}> + 
    </button> 
    </div> 
); 
}; 

const TodoList = ({todos}) => { 
    let todoNodes = todos.map(todo => { 
     return <li>{todo}</li> 
    }); 
    return <div> {todoNodes} </div>; 
} 

const Title = ({todoCount}) => { 
    return (
    <div> 
     <div> 
     <h1>To-do App {todoCount} items</h1> 
     </div> 
    </div> 
); 
} 

class TestApp extends React.Component { 
    constructor(props) { 
    super(props); 
    this.state = { data : [] } 
    } 

    addTodo(val) { 
    let todo = {text: val} 
    this.state.data.push(todo); 
    this.setState = ({data: this.state.data}); 
    console.log('state updated?') 
    } 

    render(){ 
    return (
     <div> 
     <Title todoCount={this.state.data.length}/> 
     <TodoForm addTodo={this.addTodo.bind(this)}/> 
     <TodoList todos={this.state.data}/> 
     </div> 
    ); 
    } 
} 

ReactDOM.render(<TestApp />, document.getElementById('root')); 

回答

1

很简单,像你在这里做你不变异的状态是很重要的

this.state.data.push(todo); 

这是很难调试,并增加了副作用,因为很难保持踪迹。遵循你的方法,你应该把状态复制到一个var,更新该var,然后将它作为你的状态中的新字段传递。哪些可以工作,但这也是我不建议的。一般好的方法是基于对计算新状态的旧

// this.state.data.push(todo); You can remove this line 
this.setState(prevState => ({ data: prevState.data.concat(todo) })) 

这将使用setState方法解决您的问题,并避免变异的状态,这是你永远不应该做的事,只有更新状态。

我也更新了你的TodoList,这是显示不正确,你必须访问todo的text字段才能显示。

const TodoList = ({todos}) => { 
    let todoNodes = todos.map(todo => { 
     return <li>{todo.text}</li> 
    }); 
    return <div> {todoNodes} </div>; 
} 

https://codepen.io/anon/pen/MmRVmX?editors=1010

+0

甜,感谢您的回答。 –

相关问题