1

I am new to react and trying to update parent's state but no luck so far.

Component

class InputBox extends Component {
  constructor(props) {
    super(props);
    this.type = props.type;
  }
  render() {
    return (
      <div>
        <input type={this.type}/>
      </div>
    );
  }
}

Other container where I want to use this component to toggle password

constructor(props) {
  super(props);
  this.state = {
    type: 'password',
    wording: 'Show',
  };
  this.changeState = this.changeState.bind(this);
}

changeState() {
  const oldState = this.state.type;
  const isTextOrHide = (oldState === 'password');
  const newState = (isTextOrHide) ? 'text' : 'password';
  const newWord = (isTextOrHide) ? 'Hide' : 'Show';
  this.setState({
    type: newState,
    label: newWord,
  });
}

<Wrapper>
  <InputBox type={this.state.type} />
  <Toggle onClick={this.changeState}>{this.state.wording}</Toggle>
</Wrapper>
cbr
  • 12,563
  • 3
  • 38
  • 63
userNotHere
  • 97
  • 1
  • 2
  • 11
  • check this answer https://stackoverflow.com/questions/38394015/how-to-pass-data-from-child-component-to-its-parent-in-reactjs/38397755#38397755 – Shubham Khatri Jun 20 '17 at 19:38

3 Answers3

3

You can do like this:

First, Parent component:

import React, { Component } from 'react';
import { InputBox} from './InputBox'

class componentName extends Component {
  state = {
    password: '',
    type: 'password',
    wording: 'Show',
  }

  handleShow = (word) => {
    this.setState({ wording: word })
  }

  handleChange = (e) => {
    if(!this.state.password){ 
      handleShow('Show')
    } else  {
      handleShow('Hide')
    }
    this.setState({ password: e.target.value })
  }

  render() {
    return (
      <div>
        <Wrapper>
          <InputBox
           name='password'  
           handleChange={this.handleChange} 
           password={this.state.password}
           type={this.state.type} /> . 
          <Toggle onClick={this.changeState}>{this.state.wording}
         </Toggle>
        </Wrapper>
      </div>
    );
  }
}

Now the child component:

import React from 'react';

export const InputBox = (props) => (
  <input onChange={props.handleChange} value={props.password} type={props.type}/>
)
  1. The state needs to always remain in the parent and then pass it down through props
  2. The children components usually are stateless, which means, they don't need to be a class (can be just a function that returns jsx ) and the most import, can't have state (state is only available in Class components)

Always pass the state down to children components Because no matter how far down the state is, by being passed through props it'll will always change the source, which in this case is the parent, the creator of the state

another important thing:

If you use arrow functions ES6 , there's no need to have a constructor to bind your functions.

Like this: handleSomething = () => { return ... }

another thing:

you don't need the constructor to set the state, you can simply do

state = { } 

and it automatically become part of the context this

Thinking this way you'll never fail.

Hope it helped you :)

Edivan Silva
  • 111
  • 4
2
class Child extends Component{
    constructor(props){
       super(props);
    }

    render(){
       let { parentStateChange } = this.props;
       return <input type='text' onChange={parentStateChange}/>
    }
}

class Parent extends Component{
    constructor(props){
       super(props);
       this.state = {
           content: "Something"
       }
       this.parentStateChange = this.parentStateChange.bind(this);
    }

    parentStateChange(event){
       let value = event.target.value;
       this.setState({
           content: value
       })
    }

    render(){
       let { content } = this.state;
       return <div>
           <h2>{content}</h2>
           <Child parentStateChange={this.parentStateChange}></Child>
         </div>
    }
}

I did it by passing a Parent's method to child as a props. Then Child has use this method to change Parent's state. It's called as Callback Functions.

For More References

I think this is useful for you.

Vasi
  • 1,147
  • 9
  • 16
0

A more generic (but possibly bad approach). Parent class has a function that is passed as callback to children and allows child calling setState directly. I can only see this useful in a tightly bound small component with a few children or just for proof of concept code.

/**
  * This allows children to set state of this object.
  * Might be a very bad approach, btw.
  * 
  * @param {object} newState - object to update state.
  * @param {func} cb - call back after state is updated.
  */
 doSetState = (newState, cb=null) => {
    const merge = { ...this.state, ...newState };
    cb ? this.setState(merge, cb) : this.setState(merge);
}
Josef.B
  • 942
  • 8
  • 16