2017-06-28 48 views
0

对React非常新颖,我似乎被卡住了。这是一个简单的Todo应用程序,我基本上有3个组件,基础组件,输入组件和任务组件。我已经想出了如何在每个组件中编辑状态,但是我无法从组件传递状态。React将状态传递给兄弟组件,直至父类

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都有自己的状态,我可以更新,但我怎么传递到父组件更新和添加任务的组成部分?另外我如何添加一个任务组件而不重新渲染整个事物?

+0

你不能传递从子为父值;相反,你可以在父类中写入一个函数,然后将该函数传递给child,然后在提供该子组件的值的子组件中调用该函数;像这样:https://medium.com/@ruthmpardee/passing-data-between-react-components-103ad82ebd17 –

回答

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>

相关问题