【问题标题】:React Passing state to sibling component and up to parent class将状态传递给兄弟组件和父类
【发布时间】:2017-12-01 05:18:25
【问题描述】:

对 React 非常陌生,我似乎被卡住了。这是一个简单的 Todo 应用程序,我基本上有 3 个组件,基本组件、输入组件和任务组件。我已经想出了如何编辑每个组件中的状态,但是在将状态从组件传递到组件时遇到了麻烦。

class App extends Component {
    render() {
        return (
            <div id="appContainer">
                <HeaderTitle />
                <TaskInput />
                <Task taskState={true} text="task one" />
                <Task taskState={true} text="task two" />
                <Task taskState={true} text="task three" />
            </div>
        );
    }

}

class TaskInput extends React.Component {
    constructor(props) {
        super(props);
        this.state = {}
    }
    update(e) {
        this.setState({inputValue: e.target.value});
        console.log(this.state);
    }
    taskCreate(e) {
        this.setState({text: this.state.inputValue, completeState: false});
        console.log('button clicked');
        console.log(this.state);
    }
    render () {
        return (
            <div className="taskInputContainer">
                <TaskInputField update={this.update.bind(this)} taskCreate={this.taskCreate.bind(this)} />
            </div>
        )
    }
}


class Task extends Component {
    constructor(props) {
        super();
        this.state = {
            completeState: false
        }
    }
    toggleTask (e) {
        this.setState({
            completeState: !this.state.completeState
        });
    }
    delete (item) {

    }
    render() {
        return (
            <div className="taskContainer" onClick={this.toggleTask.bind(this)}>
                <div className={"taskState " + this.state.completeState}></div>
                <div className={"taskText " + this.state.completeState }>{this.props.text}</div>
                <div className="taskDelete"><i className="fa fa-times-circle-o" aria-hidden="true"></i></div>
            </div>
        );
    }
}

const TaskInputField = (props) =>
    <div className="taskInputContainer">
        <input type="text" className="taskInputField" onChange={props.update}/>
        <i className="fa fa-plus-circle" aria-hidden="true" onClick={props.taskCreate}></i>
    </div>;

Task.propTypes = {
    text: PropTypes.string.isRequired,
    completeState: PropTypes.bool
};
Task.defaultProps = {
    text: 'Task',
    completeState: false
};

const HeaderTitle = () => (
    <h1>Davids Todo List</h1>
);

export default App;

所以在 TaskInput 中有它自己的状态,我可以更新,但是我如何将它传递给父组件来更新和添加一个 Task 组件?另外,如何在不重新渲染整个内容的情况下添加任务组件?

【问题讨论】:

  • 您不能将值从孩子传递给父母;取而代之的是,您可以在父级中编写一个带有特定参数的函数,将该函数传递给子级,然后在子组件中调用该函数,以提供来自子组件的值;像这样的东西:medium.com/@ruthmpardee/…

标签: reactjs state


【解决方案1】:

React 的documentation 中的“提升状态”一文中详细记录了此问题。

TLDR,您创建一个处理程序来更新当前组件的状态并将其作为道具传递给子组件。在下面的示例中(您的代码的修改版本),我将更改组件 App 状态的方法传递给其子组件(TaskInput 和 Tasks)。

class App extends React.Component {
  constructor() {
    super();
    this.state = {
      tasks: [],
    }
  }
    
  addTask = (e, text) => {
    e.preventDefault();
    const newTask = {
      id: new Date().getTime(),
      done: false,
      text
    };
    const newTasks = this.state.tasks.concat([newTask]);
    this.setState({
      tasks: newTasks
    })
  }
    
  toggleTask = (id) => {
    const updatedTask = this.state.tasks.filter(task => task.id === id);
    updatedTask[0].done = !updatedTask[0].done;
    const newTasks = this.state.tasks.map(task => {
      if (task.id === id) {
        return updatedTask[0];
      }
      return task;
    });
    this.setState({
      tasks: newTasks
    });
  }
    
  render() {
    return (
      <div id="appContainer">
        <HeaderTitle />
        <TaskInput addTask={this.addTask} />
        {
          this.state.tasks.length > 0 ? <Tasks tasks={this.state.tasks} toggleTask={this.toggleTask}/> : <div>no tasks yet</div>
        }
      </div>
    );
  }

}

class TaskInput extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      currentInput: ''
    }
  }
  
  handleChangeText = (e) => {
    this.setState({
      currentInput: e.target.value,
    })
  }
  
  render() {
    return (<form>
<input type="text" value={this.state.currenInput} onChange={this.handleChangeText}/><input type="submit" onClick={(e) => this.props.addTask(e, this.state.currentInput)} value="Add Task"/></form>)
  }
} 


const Tasks = (props) => (
  <div>
    {
      props.tasks.map(task => (
        <div 
          style={ task.done ? { textDecoration: 'line-through'} : {} }
          onClick={() => props.toggleTask(task.id)}
          >{task.text}</div>
      ))
    }
  </div>
);

const HeaderTitle = () => (
  <h1>Davids Todo List</h1>
);

ReactDOM.render(<App />, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="app"></div>

【讨论】:

    猜你喜欢
    • 2018-01-27
    • 2017-10-24
    • 2021-11-19
    • 1970-01-01
    • 1970-01-01
    • 2021-06-10
    • 2019-02-17
    • 2019-04-02
    • 1970-01-01
    相关资源
    最近更新 更多