¿Cómo hacer que redux-form funcione con TypeScript y styled-components?
Estoy tratando de hacer que redux-form funcione con TypeScript y styled-components. En el siguiente ejemplo de código, ¿por qué no funciona con el componente de entrada estilizado? La entrada se renderiza, pero se pierde el enfoque en cada pulsación de tecla. También se necesitan dos clics para enfocar el elemento. ¿Parece que redux-form está intentando controlar el elemento envuelto que devuelve styled-components? Tanto redux-form como styled-components usan HOC - componentes de orden superior para pasar props al elemento subyacente.
export interface ITxtProps extends WrappedFieldProps {
label?: string;
}
export const FieldHack = class extends Field<any> {};
const renderTxt = (props: ITxtProps & GenericFieldHTMLAttributes) => {
const StyledInput = styled.input`
background-color: deeppink;
`;
const notWorking = <StyledInput {...props.input} />;
const worksPerfectly = <input {...props.input} />;
return (
<div>
<div>{props.label}</div>
{notWorking}
</div>
);
}
const NormalLoginComponent = (props: {
handleSubmit?: SubmitHandler<{}, {}>;
}) => {
const { handleSubmit } = props;
return (
<form onSubmit={handleSubmit}>
{/* this does not work when using styled components: */}
<Field name={'email'} component={renderTxt} />
{/* this gives an error, property label does not exist on type... */}
{/*<Field name={'email'} component={renderTxt} label="email" />*/}
{/* this works, but no intellisense/static types */}
<FieldHack name={'email2'} component={renderTxt} label="email" />
<Field name={'password'} component={'input'} type="password" />
<Button text={'log in'} onClick={handleSubmit} />
</form>
);
};
export interface ILoginForm {
email: string;
password: string;
}
const LoginForm = reduxForm<Readonly<ILoginForm>, {}>({
form: 'loginNormal',
})(NormalLoginComponent);
Respuesta #1
Sí, finalmente lo entendí.. Cometí un error, y eso fue crear mi wrapper de styled-component dentro del método render:
const StyledInput = styled.input`
background-color: deeppink;
;
Aparentemente no es seguro aplicar un HOC - componente de orden superior dentro de render(). Así que debería funcionar al mover el HOC fuera de render:
export interface ITxtProps extends WrappedFieldProps {
label?: string;
}
export const FieldHack = class extends Field<any> {};
// wrap you HOC outside render:
const StyledInput = styled.input`
background-color: deeppink;
`;
const renderTxt = (props: ITxtProps & GenericFieldHTMLAttributes) => {
// works now :)
const notWorking = <StyledInput {...props.input} />;
const worksPerfectly = <input {...props.input} />;
return (
<div>
<div>{props.label}</div>
{notWorking}
</div>
);
}
Estaba leyendo la documentación de otra biblioteca HOC mientras descubría esto, aquí hay un enlace que explica dónde es seguro aplicar (cualquier) HOC: documentación de redux-auth-wrapper sobre HOCs
