pipino
pipino

Reputation: 89

React array hooks don't work, new values don't display

import React, { useState } from 'react';
import Tab from 'react-bootstrap/Tab';
import Tabs from 'react-bootstrap/Tabs';

import { sections } from '../../data/sections';

export const NavigationTop = () => {
    const [mySections, setMySections] = useState(sections);

    const selectSection = (id) => {
        let newSections = mySections;
        newSections[id].name = mySections[id].name + '*'; 
        setMySections(newSections);
    };
    
    return (
        <Tabs defaultActiveKey="0" id="fill-tab-example" className="mb-3" onSelect={(k) => selectSection(k)} fill> 
            {mySections.map((el) => {
                const { id, name } = el;
                return (
                    <Tab id={id} key={id} eventKey={id} title={name}></Tab>
                );
            })}
        </Tabs>
    );
}

The selectSection event is triggered and newSections contains the new values, but the page does not show the new values.

Where is my error?

Upvotes: 0

Views: 58

Answers (2)

Drew Reese
Drew Reese

Reputation: 203466

You are mutating the state object and not providing a new array reference for React's reconciliation process to trigger a component rerender.

const [mySections, setMySections] = useState(sections);

const selectSection = (id) => {
  let newSections = mySections; // <-- reference to state
  newSections[id].name = mySections[id].name + '*'; // <-- mutations
  setMySections(newSections); // <-- same reference
};

The mySections state reference never changes so React bails on rerendering the component. Shallow copy all state, and nested state, that is being updated.

Use a functional state update to correctly update from any previous state.

Example:

const selectSection = (id) => {
  setMySections(sections => sections.map(section => 
    section.id === id
      ? { ...section, name: section.name + "*" }
      : section
  ));
};

Upvotes: 1

ashish singh
ashish singh

Reputation: 6914

try this change

let newSections = [...mySections];

what this does is make a copy of your array.

if you don't make a copy, reference doesn't change, and react does a shallow comparison ( only checks the reference and not value ) to see if UI needs to be updated.

Upvotes: 0

Related Questions