- Compound React Components with Hooks + TypeScript
- Guide to Typescript and Hooks: A bit more basic but relevant
- Compound Components with React Hooks: Barebones but relevant
- Thinking in React Hooks: Complete and very useful blog post!
Last active
September 27, 2019 19:52
-
-
Save stephenway/1fb94775e6b2ff21a166ab3f7ff66015 to your computer and use it in GitHub Desktop.
WIP: Convert FormikMultiWizard to React.FC & Context
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Formik } from 'formik' | |
import React, { Children, createContext, FC, useContext, useState } from 'react' | |
import { Button } from '@material-ui/core' | |
import { IWizardProps } from './Wizard.d' | |
const WizContext = createContext({ children: null }) | |
const Wizard: FC<IWizardProps> = ({ | |
innerRef, | |
children, | |
onSubmit, | |
submitLabel = 'Submit', | |
disablePrevious = false, | |
actions, | |
initialValues, | |
}) => { | |
const [step, setStep] = useState(0) | |
const [values, setValues] = useState(initialValues) | |
const steps = { | |
last: Children.count(children) - 1, | |
current: Children.toArray(children)[step], | |
isBack: step > 0, | |
get isLast() { | |
return step === this.last | |
}, | |
} | |
const next = nextValues => { | |
setStep(Math.min(step + 1, children!.length - 1)) | |
setValues(nextValues) | |
} | |
const previous = () => { | |
setStep(Math.max(step - 1, 0)) | |
} | |
const validate = validateValues => { | |
return steps.current!.props.validate ? steps.current!.props.validate(validateValues) : {} | |
} | |
const handleFormSubmit = (submitValues, bag) => { | |
if (steps.isLast) { | |
return onSubmit(submitValues, bag) | |
} else { | |
bag.setTouched({}) | |
bag.setSubmitting(false) | |
next(submitValues) | |
} | |
} | |
return ( | |
<Formik | |
ref={innerRef} | |
initialValues={values} | |
validate={validate} | |
onSubmit={handleFormSubmit} | |
render={({ handleSubmit, isSubmitting }) => ( | |
<form onSubmit={handleSubmit}> | |
<WizContext.Provider value={{ children }}>{steps.current}</WizContext.Provider> | |
<> | |
{steps.isBack && !disablePrevious && ( | |
<Button className="qa-previous" onClick={previous}> | |
Previous | |
</Button> | |
)}{' '} | |
{actions && actions} | |
<Button | |
className={`qa-${!steps.isLast ? 'next' : 'submit'}`} | |
variant="contained" | |
color="primary" | |
type="submit" | |
disabled={steps.isLast && isSubmitting} | |
> | |
{!steps.isLast ? 'Next' : submitLabel} | |
</Button> | |
</> | |
</form> | |
)} | |
/> | |
) | |
} | |
interface IStepProps { | |
children: any | |
validate: any | |
} | |
export const Step: FC<IStepProps> = () => { | |
const { children } = useContext(WizContext) | |
return children | |
} | |
export default Wizard |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment