Home > Back-end >  React: Rerender component if prop changed
React: Rerender component if prop changed

Time:10-31

I have the problem that a child component is not re-rendered when I change a prop value via the parent component.

Parent component:

import React, { useEffect, useState } from 'react';
import "./style.scss";

import DeviceButton from "../../buttons/deviceButton/deviceButton";

function Dashboard({ socket }) {
    const [activeButtons, setActiveButtons] = useState({desk: false, shelf: false});

    function toggleLight(type, id) {
        if(type && id) {
            var buttons = activeButtons;
            buttons.desk = true;
            setActiveButtons(buttons);
            console.log(activeButtons)
        }
    }

    return(
        <div className="view">
            <div className="devices">
                <div className="buttons">
                    <DeviceButton text="Desk" active={activeButtons.desk} type="device" id="desk" event={toggleLight} />
                    <DeviceButton text="Shelf" active={activeButtons.shelf} type="device" id="shelf" event={toggleLight} />
                </div>
            </div>
        </div>
    )
}

Child component:

import React, { useState, useEffect } from 'react';
import "./style.scss";

function DeviceButton(props) {
    useEffect(() => {
        // This is only executed during initialization.
        console.log(props.active);
    }, [props.active]);
    return(
        <button className={`device-button ${props.active == true ? "active" : ""}`}  onClick={() => props.event(props.type, props.id)}>
            <span className="text">{props.text}</span>
            <span className="status">Inactive</span>
        </button>
    )
}

export default DeviceButton;

When I click on a DeviceButton the toggleLight function of the parent component is called. This causes the state to change, which is passed as prop to the child component. Unfortunately, the child component does not render again so I can use the new prop value.Unfortunately, the useEffect function is only executed when the component is initialized.

CodePudding user response:

The issue is that you're mutating the current state object rather than setting a new state object. React relies on checking referential equality when determining if state changes; mutating the object will not be seen as a new object in memory, and therefore will not prompt a rerender.

One quick way to fix the issue would be to do a shallow copy using the spread operator, which will create a new object:

function toggleLight(type, id) {
  if(type && id) {
    var buttons = {...activeButtons};
    buttons.desk = true;
    setActiveButtons(buttons);
  }
}
  • Related