2017-06-28 87 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>

相關問題