Home > Blockchain >  Update Child state from Parent using Context in React
Update Child state from Parent using Context in React

Time:05-11

I have a few buttons and "view all" button. The individual buttons load the coresponding data of that index or will show all the data by clicking the "view all" button. Problem I am running into is when I click my "view all" button in the parent it's not updating the state in the child component. On mounting it works as normal but on event handler in the "view all" it doesn't update. Any thoughts on where I am going wrong here?

JS:

...
const Context = createContext(false);

const useStyles = makeStyles((theme) => ({
  root: {
    display: "flex",
    "& > *": {
      margin: theme.spacing(1)
    }
  },
  orange: {
    color: theme.palette.getContrastText(deepOrange[500]),
    backgroundColor: deepOrange[500],
    border: "4px solid black"
  },
  info: {
    margin: "10px"
  },
  wrapper: {
    display: "flex"
  },
  contentWrapper: {
    display: "flex",
    flexDirection: "column"
  },
  elWrapper: {
    opacity: 0,
    "&.active": {
      opacity: 1
    }
  }
}));

const ToggleItem = ({ id, styles, discription }) => {
  const { activeViewAll, handleChange } = useContext(Context);
  const [toggleThisButton, setToggleThisButton] = useState();

  const handleClick = () => {
    setToggleThisButton((prev) => !prev);
    handleChange(discription, !toggleThisButton);
  };

  return (
    <>
      <Avatar
        className={toggleThisButton && !activeViewAll ? styles.orange : ""}
        onClick={handleClick}
      >
        {id}
      </Avatar>
      <p>{JSON.stringify(toggleThisButton)}</p>
    </>
  );
};

const ToggleContainer = ({ className, selected }) => {
  return (
    <div className={className}>
      {selected.map((item, idx) => (
        <div key={idx}>Content {item}</div>
      ))}
    </div>
  );
};

export default function App() {
  const data = ["first", "second", "third"];
  const classes = useStyles();
  const [selected, setSelected] = useState([]);
  const [activeViewAll, setActiveViewAll] = useState(false);

  useEffect(() => {
    setActiveViewAll(true);
    setSelected([...data]);
  }, []);

  const handleChange = (val, action) => {
    let newVal = [];
    if (activeViewAll) {
      selected.splice(0, 3);
      setActiveViewAll(false);
    }
    if (action) {
      newVal = [...selected, val];
    } else {
      // If toggle off, then remove content from selected state
      newVal = selected.filter((v) => v !== val);
    }
    console.log("action", action);
    setSelected(newVal);
  };

  const handleViewAll = () => {
    console.log("all clicked");
    setActiveViewAll(true);
    setSelected([...data]);
  };

  return (
    <Context.Provider value={{ activeViewAll, handleChange }}>
      <div className={classes.wrapper}>
        <Avatar
          className={activeViewAll ? classes.orange : null}
          onClick={handleViewAll}
        >
          <span style={{ fontSize: "0.75rem", textAlign: "center" }}>
            View All
          </span>
        </Avatar>
        {data.map((d, id) => {
          return (
            <div key={id}>
              <ToggleItem id={id} styles={classes} discription={d} />
            </div>
          );
        })}
      </div>
      <div className={classes.contentWrapper}>
        <ToggleContainer styles={classes} selected={selected} />
      </div>
    </Context.Provider>
  );
}

Codesanbox: Edit update-child-state-from-parent-using-context-in-react

  • Related