I'm using styled-components. I have to use it to make the style changes because what I need to change is nested inside Kendo React Grid, as they outline in their docs: https://www.telerik.com/kendo-react-ui/components/styling/styled-components/
I need to style the component dynamically based on props. The problem this creates is that, because a new component is created every render cycle, text inputs lose focus as you type. I tried to wrap the component in useMemo to solve this, but it causes a "Rendered fewer hooks than expected" error. It seems useRef is being called in styled() from styled-components, so when it subsequently is skipped because of useMemo, it creates the hooks mismatch.
I created a simpler example here: https://stackblitz.com/edit/react-mu6rlr-omeo5c?file=app%2Fmain.jsx
function CustomText(props){
const [state, setState] = useState('text')
const {color} = props
const Input = styled('input')`
background-color: ${color}
`
return <Input value={state} onChange={useCallback(event => setState(event.target.value))}/>
}
// loses focus on update
function CustomTextMemo(props){
const [state, setState] = useState('memoized')
const {color} = props
const Input = useMemo(
() => styled('input')`
background-color: ${color}
`,
[color]
)
return <Input value={state} onChange={useCallback(event => setState(event.target.value))}/>
}
// "Rendered fewer hooks than expected. This may be caused by an accidental early return statement."
The top text box loses focus on update. The lower memoized one hits the hook error.
What is a better pattern for solving this?
Input
like so:<Input color={color} onChange{...} value={...}/>
, then you can accesscolor
within the styled-component template literal:background: ${({ color }) => color };
. – Matt Carlotta