reactjs - Hantera anpassade komponentkryssrutor med Field som i Formik


Jag har fastnat de senaste par timmarna och försökt lista ut hur man hanterar ett formulär med en anpassad kryssrute-komponent i Formik. Jag skickar det via <Formik as > som introducerades i Formik 2.0

Problem uppstår med input type='checkbox' eftersom jag inte bara kan direkt skicka true eller false värden till det.

Nu lägger jag upp lösningen som jag är medveten om är en dålig implementering. Jag hittade egentligen inte ett sätt att korrekt skicka värden från komponenten, så jag ville hantera det som ett separat tillstånd i komponenten eftersom kryssrutan kommer att ta hand om sitt eget tillstånd.

Min anpassade inmatningskomponent är strukturerad på följande sätt

import React, { useState } from 'react';
import { StyledSwitch, Wrapper } from './Switch.styled';

type Props = {
  value: boolean;
  displayOptions?: boolean;
  optionTrue?: string;
  optionFalse?: string;
};

const Switch: React.FC<Props> = (props: Props) => {
  const { value, optionTrue = 'on', optionFalse = 'off', displayOptions = false } = props;
  const [switchVal, setSwitchVal] = useState<boolean>(value);

  const handleSwitchChange = (): void => setSwitchVal(!switchVal);

  return (
    <Wrapper styledVal={switchVal}>
      <StyledSwitch type="checkbox" checked={switchVal} onChange={handleSwitchChange} />
      {displayOptions && (switchVal ? optionTrue : optionFalse)}
    </Wrapper>
  );
};

export default Switch;

./Switch.styled använder styled-components men de är inte relevanta för denna fråga. Föreställ dig dem helt enkelt som ett <input> och ett <div> respektive

Här är komponenten som hanterar strömbrytaren

import React, { useState } from 'react';
import { Formik, Form, Field } from 'formik';
import Switch from '../../../components/forms/Switch';

const QuizMenu: React.FC = () => {
  const [isMultipleChoice, setIsMultipleChoice] = useState<boolean>(false);

  const sleep = (ms: number): Promise<number> => new Promise((resolve) => setTimeout(resolve, ms));

  return (
    <Formik
      initialValues={{ isMultipleChoice: 'false', password: '' }}
      onSubmit={async (values): Promise<boolean> => {
        await sleep(1000);
        JSON.stringify(values, null, 2);
        return true;
      }}
    >
      {
        (): any => ( // to be replaced with formik destruct, but dont want eslint problems before implementation
          <Form>
            <div>
              <Field as={Switch} onClick={setIsMultipleChoice(!isMultipleChoice)} value={isMultipleChoice === true} name="isMultipleChoice" displayOptions />
              { isMultipleChoice }
            </div>
          </Form>
        )
      }
    </Formik>
  );
};

export default QuizMenu

;

Vilket ger följande fel:

Fel: Maximalt uppdateringsdjup överskridet. Detta kan hända när en komponent upprepade gånger anropar setState inuti componentWillUpdate eller componentDidUpdate. React begränsar antalet nästlade uppdateringar för att förhindra oändliga loopar.

Jag försökte också redigera value till sträng enligt input type='checkboxed' men jag kan verkligen inte hitta ett sätt att hantera det. Om du hanterar det i en separat handleChange()-funktion blir du av med felet, men då uppdateras inte state av någon anledning.

Vad skulle vara det rätta sättet att hantera detta?