skip to Main Content

I am trying to update my child component based on parent state and similarly I am trying to update the parent state by clicking on a button in child component. Both is fine but while clicking on a button in child it’s updating the parent but instead of the only clicked child iits opening both the child how to solve the issue using react hook? I want to open only one child while clicking child but the Expand all button of parent should change to collapse all.

I am adding my codesandbox for better understanding

https://codesandbox.io/s/react-parent-child-functional-component-example-forked-xkpvsl?file=/src/Child.js

Parent to child update and child to parent by a event handler is happening but while clicking child i want to update the state of parent but not to open both the child only clicked child?

2

Answers


  1. You can take a additional state in Parent.js a long with State handler.

    const [expandCount, setExpandCount] = useState(0);
    
    const expandCountHandler = (action) => {
       if (action === "opened") {
          setExpandCount(expandCount + 1);
       } else {
          setExpandCount(expandCount - 1);
       }
    };
    

    Pass the handler in the Child component.

    <Child
        buttonName="1st button"
        handleCollapse={handleCollapse}
        color="red"
        isExpanded={isExpanded}
        expandCountHandler={expandCountHandler}
    />
    

    Call the handler from the Child.js

    onClick={() => {
       setOpen((prevOpen) => !prevOpen);
       props.expandCountHandler(open ? "closed" : "opened");
    }}
    

    In the Parent button, you need to handle onclick event based on the expandCount state.

    Give that a try.

    Login or Signup to reply.
  2. The problem is you put 2 child button inside an Child component and you pass the same open state to both of them.

    The solution is split 2 button into 2 Child component.

    There is your code

    <div>
      <div style={{ display: "flex" }}>
        {button()}
        {open ? <p style={{ color: "red" }}>1st button</p> : null}
      </div>
      <div style={{ display: "flex" }}>
        {button()}
        {open ? <p style={{ color: "green" }}>2nd button</p> : null}
      </div>
    </div>
    

    I would like to change into

    <div>
      <div style={{ display: "flex" }}>
        {button()}
        {open ? <p style={{ color: props.color }}>{props.buttonName}</p> : null}
      </div>
    </div>
    

    So you can pass the buttonName and color props to each child to custom them. And remove handleCollapse()
    from button() click event to prevent toggle both children.

    About parent node.

    Change isExpanded state to array to hold more child state. With this isExpanded state you can check did thay all expanded with every method.

    const Parent = () => {
    const [isExpanded, setIsExpanded] = useState([false, false, false, false]);
    let handleCollapse = () => {
      if (isExpanded.every((ie) => ie === true))
        setIsExpanded(new Array(4).fill(false));
      else setIsExpanded(new Array(4).fill(true));
    };
    return (
      <div>
        <button onClick={() => handleCollapse(false)}>
          {isExpanded.every((ie) => ie === true) ? "Collapse All" : "Expand all"}
        </button>
        <Child
          buttonName="1st button"
          color="red"
          isExpanded={isExpanded[0]}
          setIsExpanded={setIsExpanded}
          id={0}
        />
        <Child
          buttonName="2nd button"
          color="green"
          isExpanded={isExpanded[1]}
          setIsExpanded={setIsExpanded}
          id={1}
        />
        <Child
          buttonName="3rd button"
          color="blue"
          isExpanded={isExpanded[2]}
          setIsExpanded={setIsExpanded}
          id={2}
        />
        <Child
          buttonName="4th button"
          color="yellow"
          isExpanded={isExpanded[3]}
          setIsExpanded={setIsExpanded}
          id={3}
        />
    );
    

    };

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search