#forcing NumberInput to re-render
36 messages · Page 1 of 1 (latest)
what are you currently doing, are you using useState
show some code if you can
i managed to make it work with a react shared library (zustand`)
for some reason, state wasnt being updated
function GridBody() {
const numberContainer = useNumberContainer((state) => state.numberContainer);
const setNumberContainer = useNumberContainer((state) => state.setArray);
React.useEffect(() => {
setNumberContainer(new Array(35).fill(1));
}, [])
function onNumberSubmit(value: number | undefined, index: number) {
if (value && value.toString().length > 2 || value == 0 || value == null) return;
const arrayCopy = numberContainer;
// @ts-ignore
arrayCopy[index] = typeof value != undefined ? value : 0;
//
console.log(JSON.stringify(arrayCopy));
setNumberContainer(arrayCopy);
}
return (
<div id="grid-body">
<SimpleGrid cols={7} spacing={0}>
{
numberContainer.map((element, index) => {
console.log(element, index);
return <NumberInput value={numberContainer[index]} onChange={(val) => onNumberSubmit(val, index)} variant="filled" withAsterisk hideControls/>
})
}
</SimpleGrid>
</div>
)
}
(it still doesnt update although the log prints right)
you are using .map() but not using keys - it is important to use keys so react knows what to update properly
https://reactjs.org/docs/lists-and-keys.html
if you open your console it should also display an error about this
return (
<div id="grid-body">
<SimpleGrid cols={7} spacing={0}>
{numberContainer.map((element, index) => (
<NumberInput value={numberContainer[index]} min={1} max={10} onChange={(val) => onNumberSubmit(val, index)} variant="filled" withAsterisk hideControls/>
))}
</SimpleGrid>
</div>
)
also tried this
both examples have no key
Why “index” as a “key” attribute is not a good idea
https://www.developerway.com/posts/react-key-attribute
i can not for the life of me figure out how to update NumberInput
this is the debug messages, that 10 in the grid should be 1
return (
<div id="grid-body">
<SimpleGrid cols={7} spacing={0}>
{numberContainer.map((element, index) => {
console.log('re-rendering', `number-input-${index}`)
return <NumberInput key={`number-input-${index}`} value={numberContainer[index]} min={1} max={10} onChange={(val) => onNumberSubmit(val, index)} variant="filled" withAsterisk hideControls/>
})}
</SimpleGrid>
</div>
)
Curious, what are your codes on onNumberSubmit ? numberContainer is just a state right?
mind sharing your implementation of onNumberSubmit?
you could also try
key={`number-input-${index}-${numberContainer[index]}`}
on the NumberInput component
import create from 'zustand';
import { devtools, persist } from 'zustand/middleware';
interface NumberContainerState {
numberContainer: number[]
numberContainerRefs: HTMLInputElement[]
setArray: (by: number[]) => void
setArrayRefs: (by: HTMLInputElement[]) => void
}
export const useNumberContainer = create<NumberContainerState>()(
devtools(
persist(
(set) => ({
numberContainer: [],
numberContainerRefs: [],
setArray: (by) => set(() => ({ numberContainer: by })),
setArrayRefs: (by) => set(() => ({ numberContainerRefs: by }))
}),
{
name: 'number-storage'
}
)
)
)
this is the shared state logic
(hook)
(the ref one is the latest thing i tried)
and how about the onNumberSubmit?
function onNumberSubmit(value: number | undefined, index: number) {
if (value && value.toString().length > 2 || value == 0 || value == null) return;
const arrayCopy = numberContainer;
// @ts-ignore
arrayCopy[index] = typeof value != undefined ? value : 1;
//
console.log(JSON.stringify(arrayCopy));
setNumberContainer(arrayCopy);
}
how do you reset it though
cause i have a reset button which basically triggers the re-render
I've updated it, see my comments about that
https://beta.reactjs.org/learn/updating-objects-in-state
an array is also an object in JavaScript
ok, i didnt know about that