reactjs从父母编辑子状态

时间:2016-03-04 11:56:19

标签: reactjs

我有一个包含3个组件的应用。 第一个是App.jsx 它调用TodoList组件如下:

<TodoList items={this.state.items} loaded={this.state.loaded} />

TodoList组件呈现多个TodoListItem组件

module.exports = React.createClass({
render: function(){
  return (
    <ul>
    {this.renderList()}
    </ul>
  )
},
renderList: function(){
    var children = [];
    for(var key in this.props.items) {
      if(this.props.items[key].text){
        var listItem = this.props.items[key];
        listItem.key = key;
        children.push(
          <TodoListItem item={listItem} key={key} onEdit={this.handleItemEdit} />
        )
      }
    }
    return children;
},
handleItemEdit: function(component){
  console.log(component);
}
});

然后在我的TodolistItem组件中渲染多个li元素

module.exports = React.createClass({
getInitialState: function(){
  return {
    text: this.props.item.text,
    done: this.props.item.done
  }
},
render: function(){
  return (
    <li onClick="this.props.onEdit.bind(null,this)">{this.state.text}</li>
  )
},

});

当我点击li上的父元素函数的函数handlItemEdit被触发时,我的问题是如何在父元素的handleItemEdit函数中更改子元素的文本值? 我想要做的是当你点击一个li打开带有输入字段的bootstrap模态,更改其文本,保存并将新道具传递给TodoListItem

2 个答案:

答案 0 :(得分:0)

getInitialState组件中,你应该写TodoListItem并将项目从道具保存到状态,然后在渲染过程中将状态(不是像你做过的道具)传递到for(var key in this.state.items) { if(this.state.items[key].text){ var listItem = this.state.items[key]; listItem.key = key; children.push( <TodoListItem item={listItem} key={key} onEdit={this.handleItemEdit} /> ) } } 组件:< / p>

setState

如果您在handleItemEdit方法中致电render()handleItemEdit将会看到更新后的状态并将被执行。 在这种情况下,您需要做的只是更改TodolistItem中的状态,这将传递到props,您应该在渲染中使用state,而不是render: function(){ return ( <li onClick="this.props.onEdit.bind(null,this.props)">{this.props.text}</li> ) }, ,就像这样:

handleItemEdit

请注意,您正在传递道具onEdit,因此您必须像这样使用handleItemEdit: function(itemProps){ console.log('You clicked: ' + this.props.items[itemProps.key]); } :{/ p>

{{1}}

答案 1 :(得分:0)

I have tested solution of your problem in ECMAScript 6 syntax. It would be very easy to use this solution in your notation too. Basicaly what you have to do is to pass this from parent to child, and then use it when you bind onClick event to parent (so you can have this in event handler function) as secound parameter you pass props of the child, where key prop will point the very cilcked element. Then it is very easy to chane parent's state, this will trigger render on parent, and cascade to render child with the new (changed by user) props.

TodoList.js

class TodoList extends Component {
    render (){
        return (
            <ul>
                {this.props.items.map(function(listItem, key) {
                    return (listItem.text &&
                        <TodoListItem item={listItem} todoList={this} key={key} onEdit={this.handleItemEdit}/>
                    );
                })}
            </ul>
        )
    };

    handleItemEdit(itemProps){
        console.log('You clicked: ' + this.props.items[itemProps.key].text);
    };
}

export default TodoList;

TodoListItem.js

import React, { Component } from 'react';

class TodoListItem extends Component {
    render() {
        return (
            <li onClick={this.props.onEdit.bind(this.props.todoList, this.props.item)}>{this.props.item.text}</li>
        )
    }
}

export default TodoListItem;

I have tested it and it prints the very text you have clicked in console. This means that oyu have access to this TodoListItem and you can change state of it in TodoList component.