Estoy tratando de crear un componente de cuadro de entrada que tenga comentarios instantáneos usando Formik. Quiero que el cuadro de entrada se vuelva verde cuando la entrada del usuario coincida con una cadena predefinida (la "respuesta"), gris si la entrada coincide con el prefijo de la respuesta (incluida la cadena vacía) y rojo en caso contrario. Esta cadena se almacena como una propiedad de los valores iniciales, values.answer . La función de validate de Formik verifica si la entrada es igual a values.answer y establece values.correct = true . Luego creé una clase css correspondiente a un cuadro de entrada verde y establecí el className de la entrada condicional al valor de values.correct . El problema es que solo parece actualizarse (es decir, se vuelve verde con una entrada correcta) cuando hago clic fuera del foco del cuadro de entrada (es decir, onBlur). Me gustaría que funcione en Change. ¿Cómo haría esto?
Aquí está el código sandbox relevante: https://codesandbox.io/s/instant-feedback-box-lub0g?file=/src/Frame.js
Buen problema, pero has complicado demasiado tu código un poco 😉 Algunos comentarios:
true durante onBlur de forma predeterminada. Puede anular esto usando setTouched() , pero me pareció más simple usar values en lugar de touched en su formulariovalues lo más mínimo posible, solo está destinado a acceder a los valores de entrada, por lo que no es necesario que se le asigne una hint y una answererrors y no establecer valores, por lo tanto, elimine asignaciones como values.correct = trueisDisabled en estado, puede derivarlo de formik.submitCount y formik.isSubmitting const Note = () => { const [showFrame, setShowFrame] = useState({ 1: true }); const onCorrectSubmission = (frameId) => { setShowFrame({ ...showFrame, [frameId]: true }); }; const text = "What is the sum of the first three natural numbers? (give answer as a word, ie one, two etc.)"; const hint = "The first three natural numbers are 1, 2, and 3"; const answer = "six"; return ( <div> <h1>Induction</h1> {showFrame[1] ? ( <Frame id={1} text={text} hint={hint} answer={answer} onCorrectSubmission={onCorrectSubmission} /> ) : null} {showFrame[2] ? ( <Frame id={2} text={text} hint={hint} answer={answer} onCorrectSubmission={onCorrectSubmission} /> ) : null} </div> ); }; const Frame = ({ id, text, hint, answer, values, onCorrectSubmission, ...props }) => { const validate = (values) => { const errors = {}; if (!answer.startsWith(values.cloze)) { errors.cloze = hint; } else if (values.cloze !== answer) { errors.cloze = true; } return errors; }; const formik = useFormik({ initialValues: { cloze: "" }, validate, onSubmit: (values) => { onCorrectSubmission(id + 1); } }); const isFinished = formik.isSubmitting || formik.submitCount > 0; return ( <form enablereinitialize={true} onSubmit={formik.handleSubmit}> <p>{text}</p> <input id="cloze" name="cloze" type="text" autoComplete="off" {...formik.getFieldProps("cloze")} disabled={isFinished} className={`input ${!answer.startsWith(formik.values.cloze) ? "invalid-input" : ""} ${formik.values.cloze && !formik.errors.cloze ? "valid-input" : ""} `} /> {formik.values.cloze && formik.errors.cloze ? ( <div>{formik.errors.cloze}</div> ) : null} <button disabled={!!formik.errors.cloze || isFinished} type="submit"> Submit </button> </form> ); }; export default Frame;