Pleats
Pleats

Reputation: 59

Updating parent component state from child component

I have one parent component that holds state of clicking : if file is clicked or not.

Files come from child component.

I know that I can use props and call function from parent, but doing that, I get this.props.handleStateChange is not a function

    export class Parent extends Component {
        constructor(props) {
        super(props);
        this.state = {
            clickable: false
        };

        this.handleStateChange = this.handleStateChange.bind(this);
        }

        handleStateChange = (val) => {
            this.setState({ clickable: val })
        }

        render() {
            return (
                <Child handleStateChange={this.handleStateChange} />
            );
        }
    }

    class Child extends Component {
        constructor(props) {
            super(props);
            this.state = {
            clickable: false
            };
        }

        handleClick = () => {
            this.state.clickable ? this.setState({ clickable: false }) : 
            this.setState({ clickable: true });

            this.props.handleStateChange(this.state.clickable)
        }

        render() {
            return (
                <div className={this.state.clickable ? 'clickable' : null} 
                >
                    <img className="item" src={file} alt="file" onClick= 
                {this.handleClick} />
                </div>
            );
        }
    }

Any ideas what am I missing there?

Upvotes: 1

Views: 71

Answers (2)

larz
larz

Reputation: 5766

setState is asynchronous, so using your newly set state immediately after isn't guaranteed to work. Instead, try this for handleClick:

handleClick = () => {
    this.setState(prevState => {
        this.props.handleStateChange({ !prevState.clickable });
        return { clickable: !prevState.clickable };
    })
}

That said, you're maintaining the same state in the parent and child. Probably better to set it in the parent (from the child) and pass it to the child as a prop.

Also also, since you're using an arrow function, you don't need to bind any of your functions in the constructor.

Upvotes: 1

Vencovsky
Vencovsky

Reputation: 31625

Here everything is working fine, no errors.

If the code you add in your question isn't the real code you are working with, maybe try checking for typos.

Probably you are passing the prop with the wrong/different name.

Some tips that aren't related to the question

Instead of

this.state.clickable
  ? this.setState({ clickable: false })
  : this.setState({ clickable: true });

You should do

this.setState(prevState => ({clickable: !prevState.clickable}))

Upvotes: 1

Related Questions