简体   繁体   中英

React js state management

 class Todo extends React.Component { constructor(props) { super(props); this.state = { saveText: '', } this.handleSaveText = this.handleSaveText.bind(this); this.displayText = this.displayText.bind(this); } handleSaveText(saveText) { this.setState({ saveText: saveText }) } render() { return ( <div> <Save saveText = {this.state.saveText} onSaveTextChange = {this.handleSaveText} /> <Display saveText = {this.state.saveText} /> </div> ); } } class Save extends React.Component { constructor(props) { super(props); this.handleSaveText = this.handleSaveText.bind(this); } handleSaveText(e) { this.props.onSaveTextChange(e.target.value); } render() { return ( <div> <input type = "text" value = { this.props.saveText } onChange = { this.handleSaveText } /> <input type = "button" value = "save" onClick = { this.displayText } /> </div> ); } } class Display extends React.Component { render() { var todos = []; var todo = this.props.saveText; //todos.push(todo); return ( <div> { todos } </div> ); } } ReactDOM.render( <Todo / > , document.getElementById('root') ) 
 <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> 

I am new to react still trying to figure out how state works.I am trying to implement a simple todo app which takes in an input and displays an output on the screen after click of a button.

According to the minimal UI representation I broke the UI into two parts, the first contains the Save class which has an input box and a button. The second contains a display class which will display the contents of the input box.

I am storing the value of input box in state.

How can I pass that state into Display class and display the values on the screen?

Codepen Link

This will do it:

class Todo extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      saveText: '',
      displayText: []
    }
    this.handleSaveText = this.handleSaveText.bind(this);
    this.displayText = this.displayText.bind(this);
  }
  handleSaveText(saveText) {
    this.setState({
      saveText: saveText
    })
  }
  displayText(text) {
    let newDisplay = this.state.displayText;
    newDisplay.push(text);
    this.setState({displayText: newDisplay});
  }
  render() {
    return (
      <div>
      <Save saveText = {this.state.saveText}
      onSaveTextChange = {this.handleSaveText}
      displayText={this.displayText}
      /> 
      <Display displayText = {this.state.displayText}
      /> </div>
    );
  }
}
class Save extends React.Component {
  constructor(props) {
    super(props);
    this.handleSaveText = this.handleSaveText.bind(this);
    this.displayText = this.displayText.bind(this);
  }
  handleSaveText(e) {
    this.props.onSaveTextChange(e.target.value);
  }
  displayText() {
    this.props.displayText(this.props.saveText);
  }
  render() {
    return ( <div>
      <input type = "text"
      value = {
        this.props.saveText
      }
      onChange = {
        this.handleSaveText
      }
      /> <input type = "button"
      value = "save"
      onClick = {
        this.displayText
      }
      /> </div>
    );
  }
}
class Display extends React.Component {
  render() {
    return ( <div> {
        this.props.displayText
      } </div>
    );
  }
}

ReactDOM.render( <Todo / > ,
  document.getElementById('root')
)

You can't push to the array in the render method because that won't exist anymore after it re-renders when it receives new props from you clicking the button again. My method saves an array of previous responses as "displayText" and sends that to the display component. Note that this method will display the entire array as a single line with no spaces. In practice you'll want to map it by doing this:

this.props.displayText.map((text, idx) => (<div key={idx}>{text}</div>));

Here is working example of todo list.

 class Todo extends React.Component { constructor(props) { super(props); this.state = { text: '', list: [] } // this.handleSaveText = this.handleSaveText.bind(this); this.addTodo = this.addTodo.bind(this); } handleSaveText(text) { this.setState({ text: text }) } addTodo(saveText) { var list = this.state.list; list.push(saveText); this.setState({ list: list }); // to save to localstorage, uncomment below line // window.localStorage.setItem('todos', list); } render() { return ( < div > < Save text = { this.state.text } onClick = { this.addTodo } /> < Display list = { this.state.list } /> < / div > ); } } class Save extends React.Component { constructor(props) { super(props); this.state = { input: this.props.text || '', } this.onChange = this.onChange.bind(this); this.addToTodo = this.addToTodo.bind(this); } onChange(e) { this.setState({ input: e.target.value }); } addToTodo() { this.props.onClick(this.state.input); this.setState({ input: '' }); } render() { return ( < div > < input type = "text" value = { this.state.input } onChange = { this.onChange } /> <input type = "button" value = "save" onClick = { this.addToTodo } /> </div > ); } } class Display extends React.Component { constructor(props) { super(props); this.state = { todos: [] } } componentWillReceiveProps(nextProps) { this.setState({ todos: nextProps.list }); } render() { var i = 1; var renderList = this.state.todos.map((name) => { return <div key = { i++ } > { name } < /div>; }); return ( < div > { renderList } < /div>); } } ReactDOM.render( < Todo / > , document.getElementById('root') ) 
 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>My React Project on CodePen</title> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/10up-sanitize.css/4.1.0/sanitize.css"> <link rel="stylesheet" href="css/style.processed.css"> </head> <body> <div id="root"></div> <script src="https://npmcdn.com/react@15.3.0/dist/react.min.js"></script> <script src="https://npmcdn.com/react-dom@15.3.0/dist/react-dom.min.js"></script> </body> </html> 

If you are trying create a todo list, you can tweak a little bit by adding array list in the main TODO component, and it down to display component.

save component you just have to handle the input change and on click function.

simple enough.

You must use:

componentWillReceiveProps(nextProps)

in your Display Component.

This is a working example:

 class Todo extends React.Component { constructor(props) { super(props); this.state = { todos: [] } this.handleSaveText = this.handleSaveText.bind(this); } handleSaveText(saveText) { let todos = this.state.todos; todos.push(saveText); this.setState({ todos: todos }); } render() { return ( <div> <Save onSaveTextClick = {this.handleSaveText} /> <Display todos = {this.state.todos} /> </div> ); } } class Save extends React.Component { constructor(props) { super(props); this.state = { saveText: '' } this.handleSaveText = this.handleSaveText.bind(this); this.handleChangeText = this.handleChangeText.bind(this); } handleChangeText(e){ this.setState({saveText: e.target.value}); } handleSaveText(e) { this.props.onSaveTextClick(this.state.saveText); } render() { return ( <div> <input type = "text" onChange = { this.handleChangeText } /> <input type = "button" value = "save" onClick = { this.handleSaveText } /> </div> ); } } class Display extends React.Component { constructor(props){ super(props); this.state = { todos: [] } } componentWillReceiveProps(nextProps){ this.setState({todos: nextProps.todos}); } render() { let todos = this.state.todos.map((todo)=>{return <div>{todo}</div>}); return ( <div> { todos } </div> ); } } ReactDOM.render( <Todo / > , document.getElementById('root') ) 
 <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="root"></div> 

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM