MSOACC
MSOACC

Reputation: 3665

React component not refreshing when state changed

I have a React component that takes an array as a parameter. From this array it generates a list. In the parent component, the array is a state variable and whenever that state variable is updated I want the changes to be reflected in the child component.

What's happening is the component is being rendered once but none of the changes are being shown.

App.js:

import heatData from "./config/heats.json";

export default function App() {
    const [selectedHeat, setSelectedHeat] = useState(heatData.heats.find((x) => x.heatNumber === 1));
    const [selectedHeatNumber, setSelectedHeatNumber] = useState(1);

    const heats = heatData.heats;
    const heatEvents = ["EventA", "EventB", "EventC", "EventD"];

    useEffect(() => {
        const _selectedHeat = heatData.heats.find((x) => x.heatNumber === selectedHeatNumber);
        setSelectedHeat(_selectedHeat);
    }, [selectedHeatNumber]);

    return (
        <div>
            <div>
                <ul>
                    {heats.map((heat, i) => (
                        <li onClick={() => setSelectedHeatNumber(heat.heatNumber)}>
                            Heat #{heat.heatNumber}
                        </li>
                    ))}
                </ul>

                <div>
                    {heatEvents.map((event, i) => (
                        // This renders once but when selectedHeat changes it doesnt re-render
                        <EventCard athletes={selectedHeat.athletes} />
                    ))}
                </div>
            </div>
        </div>
    );
}

heats.json that's being imported:

{
    "heats": [
        {
            "heatNumber": 1,
            "athletes": ["PersonA, PersonB, PersonC"]
        },
        {
            "heatNumber": 2,
            "athletes": ["PersonD, PersonE, PersonF"]
        }
    ]
}

EventCard.js:

export default function EventCard({ athletes }) {
    const [userPrediction, setUserPrediction] = useState([...athletes]);
    
    // Add methods to manipulate userPrediction

    return (
        <table>
            <tbody>
                {userPrediction.map((athlete, i) => (
                    <tr key={i}>
                        <td>{athlete}</td>
                        <td>Up</td>
                        <td>Down</td>
                    </tr>
                ))}
            </tbody>
        </table>
    );
}

Here's the process:

The problem is that clicking the button changes the heat but the athletes in EventCard do not update.

Upvotes: 0

Views: 123

Answers (1)

bakar_dev
bakar_dev

Reputation: 996

You should add this useEffect to your EventCard.js component, because you are setting the state with athletes only first time and the state is not updating when the props change, so you should keep track the change in props and then update state accordingly. CodeSandBox

useEffect(() => {
    setUserPrediction([...athletes]);
  }, [athletes]);

Or you can use athletes props directly like:

{athletes.map((athlete, i) => (
          <tr key={i}>
            <td>{athlete}</td>
            <td>Up</td>
            <td>Down</td>
          </tr>
        ))}

Upvotes: 1

Related Questions