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?
CodePudding user response:
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
));
};
CodePudding user response:
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.