0

I have the following code in my React component:

class TheComponent extends Component{

    constructor(props) {

        super(props);

        this.state = {
            a: '',
            b: ''
        };
    }

    output = (data) => {

        this.setState({
            a: data.a,
            b: data.b
        });
    }

    render(){
        return(<ChildrenComponent outputValues={this.output.bind(this)}/>);
    }
}

When I call the output method from the same component, it works perfectly well, and the state is changed successfully. But when I call it from my ChildrenComponent it doesn't work, and the state never changes.

So I've added the following code to the output function in order to find out what's going on: console.log(this.setState). And the result is that the "setState" function is there.

So, if the function setState is properly bound to output, why it doesn't work? And why it does works only when output is called from the current component?`

Captain
  • 105
  • 1
  • 15
  • You don't need to bind like that if you're using an arrow function. – Colin Ricardo Mar 24 '19 at 22:05
  • I am actually not able to repro this behavior, passing to my child component works fine: https://repl.it/repls/TealLivelyScale – y2bd Mar 24 '19 at 22:09
  • yes @y2bd, this is very strange. It should work, but not sure what's happening. – Captain Mar 24 '19 at 23:05
  • You're right @Colin, but even when I remove the binding, it doesn't work either – Captain Mar 24 '19 at 23:08
  • @Captain can you post your full code please? – Colin Ricardo Mar 24 '19 at 23:13
  • The full code has more than 100 lines of code :[ it's too big – Captain Mar 25 '19 at 01:14
  • @Captain what makes you think it's not working? I don't see you using your state anywhere in your code, which makes me think we need to see MORE of your code to help you. – larz Mar 25 '19 at 01:23
  • I assume `render() = > {` is a typo when you typed out the example code? This should be `render = () => {` – Jamie - Fenrir Digital Ltd Mar 25 '19 at 01:37
  • @larz, there I edited the code and added the state details. – Captain Mar 25 '19 at 01:46
  • Sorry @EvilGeniusJamie, I misstyped it. Now I fixed it in the code example. I don't understand why setState is not working – Captain Mar 25 '19 at 01:50
  • 1
    @Captain seeing how you set the initial state in the constructor isn't...constructive ;) . WHAT makes you think that when you call `output` the state isn't being updated? You aren't using `this.state.a` in your `render` method, so I have trouble helping you trouble shoot. Maybe add a `console.log(this.state.a)` inside your `render` method and see if that displays what you expect on the re-render? Maybe `console.log(data)` and make sure there is a` data.a` in there inside your `output` method. We are only seeing half the code. – larz Mar 25 '19 at 01:53
  • @larz, yes, but I have made the console.log, and also I have the react extension for chrome, and checked the state with both of them, and it doesn't change. I'm fixing this using Redux, but I will keep this question open in case somebody else has the same issue, and can find the answer here – Captain Mar 25 '19 at 14:00

1 Answers1

2

Your code looks pretty good to me. I think you're just getting a bit confused with what setState does. setState is a built in React function and running console.log(this.setState) will therefore always log a function, specifically that function.

I'm not sure how you are calling your prop in the child component, but the example below allows the child component to set the parents state to the data object above the render functions return as well as logging the parent state to the console.

class TheComponent extends Component{
    constructor(props) {
        super(props);
        this.state = {
            a: '',
            b: ''
        };
     }

     setValues = (data) => {
        this.setState({
            a: data.a,
            b: data.b
        });
      }

     outputValues = () => {
         console.log(this.state);
     }

      render(){
        return (
            <ChildrenComponent set={this.setValues} output={this.outputValues}/>
            <p>{this.state.a}</p>
        );
      }
    }
class ChildrenComponent extends Component{
      render() {
        const data = { a: 'foo', b: 'bar' };
        return (
            <button onClick={() => this.props.set(data)}>change parent state</button>
            <button onClick={this.props.outputValues}>console.log parent state</button>
        );
      }
    }
Nick Hu
  • 46
  • 1
  • 2