【问题标题】:reactjs edit child state from parentreactjs从父级编辑子状态
【发布时间】:2016-03-05 02:36:44
【问题描述】:

我有一个包含 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 打开带有输入字段的引导模式,更改其文本,保存并将新道具传递给 TodoListItem

【问题讨论】:

    标签: reactjs


    【解决方案1】:

    TodoList 组件中,您应该编写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} />
        )
      }
    }
    

    如果您在handleItemEdit 方法中调用setStaterender() 将看到更新的状态并被执行。 在这种情况下,您需要做的就是更改handleItemEdit 中的状态,这将传递给TodolistItem,您应该在其中使用props,而不是在渲染中使用state,如下所示:

    render: function(){
      return (
        <li onClick="this.props.onEdit.bind(null,this.props)">{this.props.text}</li>
      )
    },
    

    注意你正在传递道具 onEdit,所以你必须像这样 chane handleItemEdit

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

    【讨论】:

    • 非常感谢您的回答!因为 todoList 中的道具来自 http 请求,所以我添加了 componentWillReceiveProps: function(){ this.setState({items:this.props.items});现在在handleItemEdit 中我如何只能编辑点击的li 的值?我可以按它的键来做吗?
    • handleItemEdit 实际上应该在 TodolistItem 组件中而不是在 TodoList 组件中...这将解决您的问题
    • 您也可以阅读此article,了解如何处理通信 beetwen 组件以另一种方式解决您的问题(正如您最初想要的那样)
    • 是的,如果我想从其组件内部编辑 TodoListItem。我的问题是我想从 TodoList 组件编辑它,因为在这个组件中存在将显示输入元素的模式,以便编辑 TodoListItem
    • 我已经更新了我的答案,希望这会奏效,因为我目前无法测试它;)
    【解决方案2】:

    我已经用 ECMAScript 6 语法测试了您的问题的解决方案。在你的符号中使用这个解决方案也很容易。基本上你要做的是将this从父级传递给子级,然后在将onClick事件绑定到父级时使用它(这样你就可以在事件处理函数中有this)作为第二个参数传递props孩子,key 道具将指向非常 cilcked 元素。然后很容易改变父级的状态,这将触发父级渲染,并级联以使用新的(由用户更改)道具渲染子级。

    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;
    

    我已经对其进行了测试,它会打印您在控制台中单击的文本。这意味着 oyu 可以访问这个 TodoListItem 并且您可以在 TodoList 组件中更改它的状态。

    【讨论】:

      猜你喜欢
      • 2016-11-03
      • 2021-10-29
      • 2020-06-26
      • 2015-04-15
      • 1970-01-01
      • 2014-10-09
      • 2019-01-28
      • 1970-01-01
      • 2021-11-05
      相关资源
      最近更新 更多