0

How do I pass a state attribute from parent to child? In the following implementation, the Dropdown component has a state "isActive" and I want to access it in the Button component to attach propper styling to it. The Dropdown has to generic as it is supposed to take different sorts of buttons.

<Dropdown items="...">
  <Button active ="false" />
</Dropdown>

Dropdwon.js

...

    constructor(props){
        super(props)
        this.state = {
         isActive: true,
        }
    }

    render (){
        return (
               <div className={styles.toggle} onClick={(event) => this.showMenu(event)}>
                    {this.props.children} /* want to set active prop for the child button here */
                </div>
        );
} 

...
user1255102
  • 486
  • 4
  • 16
  • 2
    Is it? https://stackoverflow.com/questions/32370994/how-to-pass-props-to-this-props-children – iamhuynq Mar 20 '20 at 09:19
  • 3
    Does this answer your question? [How to pass props to {this.props.children}](https://stackoverflow.com/questions/32370994/how-to-pass-props-to-this-props-children) – Treycos Mar 20 '20 at 09:19

3 Answers3

1

Aside from the answer I linked, there might be another way of achieving this that I didn't see mentioned.

You can send a function as a children element of your dropdown which will take isActive as a variable :

<Dropdown items="...">
  {isActive => <Button active={isActive} />}
</Dropdown>

Then, is the render function, simply call the function and send your state value as a parameter :

render(){
    return (
        <div className={styles.toggle} onClick={(event) => this.showMenu(event)}>
            {this.props.children(this.state.isActive)}
        </div>
    );
} 
Treycos
  • 7,373
  • 3
  • 24
  • 47
1

You have two possibilities:

  1. Lift your Dropdown state and keep it in its parent component;
  2. Use useContext hook;

The first approach would be better, but it may not be good for your application (I cannot know that). Let me make an example for both cases.


This is an example where I've lifted the isActive state to the parent component.

const ParentComponent = () => {
    const [isActive, setIsActive] = useState(false);

    handleIsActiveChange = (newValue) => {
        setIsActive(newValue);
    }

    <Dropdown isActive={isActive} setIsActive={handleIsActiveChange}>
        <Button isActive={isActive} />
    </Dropdown>
}

const Dropdown = props => {
    // You can use `props.isActive` to know whether the dropdown is active or not.
    // You can use `props.handleIsActiveChange` to update the `isActive` state.
}

const Button = props => {
    // You can use `props.isActive` to know whether the dropdown is active or not.
}

Instead, this exploits the useContext API:

const dropdownContext = React.createContext(null);

const Dropdown = props => {
    const [isActive, setIsActive] = useState(false);

    return (
        <dropdownContext.Provider value={{ isActive }}>
            {props.children}
        </dropdownContext.Provider>
    );
}

const Button = props => {   
    const dropdownCtx = React.useContext(dropdownContext);

    // You can use `dropdownCtx.isActive` to know whether the dropdown is active or not.
}
Jolly
  • 1,678
  • 2
  • 18
  • 37
0
<Dropdown >
  <Button isActive={this.state.isActive} />
</Dropdown>

In your button get it with this.props.isActive

Burak Gavas
  • 1,304
  • 1
  • 9
  • 11