React component state not updating with passed props

Tags: , , ,



I have created an Accordion component which has data(object) and expanded(boolean) as props. expanded props is used to set the expanded/collapsed state of this component passed as a prop.

const DeltaAccordion = ({ index, data, expanded = true }) => {

Accordion component also has an internal state

const [isExpanded, setIsExpanded] = useState(expanded);

which is used for expanding/collapsing the accordion. Below is my complete component

Accordion.jsx

import React, { useState } from "react";

// styles
import styles from "./index.module.scss";

const Accordion = ({ index, data, expanded = true }) => {
  // state
  const [isExpanded, setIsExpanded] = useState(expanded);

  console.log(data.name, `prop-val==${expanded}`, `inner-state==${isExpanded}`);
  return (
    <div
      className={`${styles.container} caption ${isExpanded && styles.expanded}`}
    >
      <div className={styles.header} onClick={() => setIsExpanded(!isExpanded)}>
        <div>{data.name}</div>
        <div>Click</div>
      </div>
      <div className={styles.content}>
        {data.newValue && (
          <div className={styles.newValue}>
            <span>{data.newValue}</span>
          </div>
        )}
        {data.oldValue && (
          <div className={styles.oldValue}>
            <span>{data.oldValue}</span>
          </div>
        )}
      </div>
    </div>
  );
};
export default Accordion;

The parent component has a list of data and it loops through the list to create an accordion for each data item.

App.js file

{dataList.map((data, index) => (
        <Accordion data={data} expanded={!collpaseAll} index={1} />
))}

Here goes problem

There is also a button in my App.js file which is for either expanding/collapsing all the accordions together.
But when I pass its value as prop expanded to the accordion component then this value is not getting applied to the internal isExpanded state of the accordion component.

Here is live running code at codesandbox: https://codesandbox.io/s/goofy-nobel-qfxm1?file=/src/App.js:635-745

Answer

Inside the Accordion

const [isExpanded, setIsExpanded] = useState(expanded);

This line will take first time(on first render) value. To assign it next time(rerender) value you need to add a effect

useEffect(() => {
   setIsExpanded(expanded);
}, [expanded]);

And in your case, you can use the props expanded directly inside Accordion, you dont need to take it in local state.



Source: stackoverflow