Stack Overflow Asked by Sunyatasattva on February 1, 2021
I’ve got a parent component in which I initialize some piece of state, which I then pass down to the children components so that they can update that. However, when the update is triggered, the component tree is re-rendered and my inputs lose focus. Adding a key
did not help.
// App.tsx
export function App(props) {
const useVal = useState("");
return (
<Router>
<Switch>
<Route
exact
path="/"
component={() => (
<StartScreen
useVal={useVal}
/>
)}
/>
// ...
</Router>
);
}
// StartScreen.tsx
interface StartScreenProps {
useVal: [string, React.Dispatch<React.SetStateAction<string>>];
}
function bindState<T>(
[value, setState]: [T, React.Dispatch<React.SetStateAction<T>>]
) {
return {
value,
onChange: ({ value }: { value: T }) => setState(value)
}
}
export const StartScreen = (props: StartScreenProps) => {
return (
<form>
<InputField
key="myInput"
{...bindState(props.useVal)}
/>
</form>
);
}
So, now when I start typing on my InputField
(which is basically a wrapper on an <input>
) on StartScreen.tsx
, the input constantly loses focus as the component is totally re-rendered (I can see it in the DOM).
This happens because you are passing a function to the Route
's component
prop (I assume you are using react-router-dom
) :
From the docs :
If you provide an inline function to the component prop, you would create a new component every render. This results in the existing component unmounting and the new component mounting instead of just updating the existing component.
To solve this problem use the render
prop :
<Route
exact
path="/"
render={() => (
<StartScreen
useVal={useVal}
/>
)}
/>
This allows for convenient inline rendering and wrapping without the undesired remounting explained above.
Answered by Mohamed Ramrami on February 1, 2021
Get help from others!
Recent Answers
Recent Questions
© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP