I have a child ponent that is supposed to display names based on a visibility filter with checkboxes. I use a dictionary to keep track of the checked state for each name. However, when I update the dictionary the child does not update.
Here is an example:
These are the ponents:
const App = () => {
const [names, setNames] = useState(seedNames);
const [hidden, setHidden] = useState(new Map());
const handleHidden = e => {
const name = e.target.name;
const hidden = e.target.checked;
setHidden(hidden.set(name, hidden));
};
return (
<div className="App">
<VisibilityFilter
names={names}
hidden={hidden}
handleHidden={handleHidden}
/>
<DisplayNames names={names} hidden={hidden} />
</div>
);
};
const VisibilityFilter = ({ names, hidden, handleHidden }) => {
return (
<div>
{names.map(name => (
<div key={name}>
<input
type="checkbox"
name={name}
checked={hidden.get(name)}
onChange={handleHidden}
defaultChecked
/>
<span>{name}</span>
</div>
))}
</div>
);
};
const DisplayNames = ({ names, hidden }) => {
const visibleNames = names.filter(name => !hidden.get(name));
return (
<div>
{visibleNames.map(name => (
<div key={name}>{name}</div>
))}
</div>
);
};
I have a child ponent that is supposed to display names based on a visibility filter with checkboxes. I use a dictionary to keep track of the checked state for each name. However, when I update the dictionary the child does not update.
Here is an example: https://codesandbox.io/s/8k39xmxl52
These are the ponents:
const App = () => {
const [names, setNames] = useState(seedNames);
const [hidden, setHidden] = useState(new Map());
const handleHidden = e => {
const name = e.target.name;
const hidden = e.target.checked;
setHidden(hidden.set(name, hidden));
};
return (
<div className="App">
<VisibilityFilter
names={names}
hidden={hidden}
handleHidden={handleHidden}
/>
<DisplayNames names={names} hidden={hidden} />
</div>
);
};
const VisibilityFilter = ({ names, hidden, handleHidden }) => {
return (
<div>
{names.map(name => (
<div key={name}>
<input
type="checkbox"
name={name}
checked={hidden.get(name)}
onChange={handleHidden}
defaultChecked
/>
<span>{name}</span>
</div>
))}
</div>
);
};
const DisplayNames = ({ names, hidden }) => {
const visibleNames = names.filter(name => !hidden.get(name));
return (
<div>
{visibleNames.map(name => (
<div key={name}>{name}</div>
))}
</div>
);
};
Share
Improve this question
edited Mar 22, 2019 at 19:09
Travis S.
asked Mar 22, 2019 at 18:59
Travis S.Travis S.
3431 gold badge4 silver badges14 bronze badges
0
1 Answer
Reset to default 11The use of immutable state is idiomatic to React, it's expected that simple types like plain objects and arrays are used.
Map set
returns the same map, while useState
supports only immutable states. In case setter function is called with the same state, a ponent is not updated:
setHidden(hidden.set(name, hidden))
The state should be kept immutable:
setHidden(new Map(hidden.set(name, hidden)))
This may introduce some overhead and defy possible benefits of ES6 Map
. Unless Map
features like strict item order and non-string keys are in demand, it's preferable to use plain object for the same purpose.