Closed zifahm closed 4 years ago
Maybe thats not it, im missing something? this is how my wizard look
<FormikWizard
steps={steps}
onSubmit={handleSubmit}
render={FormWrapper}
Form={({ children }: any) => children}
/>
is there something i should do to make things work in React Native?
Hmm i looked into the code and got, wizard.next from the FormWrapper prop, But this is not fun without the handleSubmit for checking with yup.
Wrote a whole new prop for triggering handleSubmit inside Formwrapper
Ohh I see now, I could have used the context and just use handle submit or submitform from there.
Ohh I see now, I could have used the context and just use handle submit or submitform from there.
@zifahm Could you please share what you have done?
@ataravati
const { submitForm } = useFormikContext<MyFormikValues>();
return (
<View>
{children}
<ButtonContainer canGoBack={canGoBack}>
{canGoBack && (
<Button onPress={goToPreviousStep} title="Back" color="#404040" />
)}
<Button
onPress={submitForm}
title={isLastStep ? "Submit" : "Next"}
color="#595959"
/>
</ButtonContainer>
</View>
);
@ataravati
const { submitForm } = useFormikContext<MyFormikValues>(); return ( <View> {children} <ButtonContainer canGoBack={canGoBack}> {canGoBack && ( <Button onPress={goToPreviousStep} title="Back" color="#404040" /> )} <Button onPress={submitForm} title={isLastStep ? "Submit" : "Next"} color="#595959" /> </ButtonContainer> </View> );
Thank you!
Maybe thats not it, im missing something? this is how my wizard look
<FormikWizard steps={steps} onSubmit={handleSubmit} render={FormWrapper} Form={({ children }: any) => children} />
@zifahm could you show me an example of how to implement this on React Native, please? I can't fully understand how I'm supposed to use it 😞
I actually did a few tweaks to the formike wizard @adrrian17 by removing Form prop in the formik wizard. also added triggerSubmit as a prop so I could avoid using context api take a look
import { Formik, FormikErrors, FormikProps } from "formik";
import produce from "immer";
import React from "react";
import {
Step as AlbusStep,
Steps as AlbusSteps,
Wizard as AlbusWizard,
WizardContext,
WizardProps
} from "react-albus";
import { View } from "react-native";
import { withNextInputAutoFocusForm } from "react-native-formik";
import { Schema } from "yup";
export type FormikWizardBaseValues = any;
const Form = withNextInputAutoFocusForm(View);
export interface FormikWizardContextValue<V = any, S = any> {
status: S;
setStatus: React.Dispatch<React.SetStateAction<S>>;
values: V;
setValues: React.Dispatch<React.SetStateAction<V>>;
}
export interface FormikWizardStepType {
id: string;
component: React.SFC<{}>;
validationSchema?: Schema<any>;
validate?: (values: any) => void | object | Promise<FormikErrors<any>>;
initialValues?: FormikWizardBaseValues;
actionLabel?: string;
onAction?: (
sectionValues: FormikWizardBaseValues,
formValues: FormikWizardBaseValues
) => Promise<any>;
keepValuesOnPrevious?: boolean;
}
export interface FormikWizardWrapperProps<Values, Status = any>
extends FormikWizardContextValue<Values, Status> {
canGoBack: boolean;
goToPreviousStep: () => void;
triggerSubmit: () => void;
currentStep: string;
actionLabel?: string;
isLastStep: boolean;
steps: string[];
wizard: WizardContext;
children: React.ReactNode;
isSubmitting: boolean;
}
export interface FormikWizardProps<Values, Status = any> {
steps: FormikWizardStepType[];
render: React.SFC<FormikWizardWrapperProps<Values, Status>>;
onSubmit: (values: Values) => void | Promise<void>;
formikProps?: Partial<FormikProps<Values>>;
albusProps?: Partial<WizardProps>;
}
function getInitialValues(steps: FormikWizardStepType[]) {
return steps.reduce<FormikWizardBaseValues>((curr, next) => {
curr[next.id] = next.initialValues;
return curr;
}, {});
}
const FormikWizardContext = React.createContext<FormikWizardContextValue | null>(
null
);
interface FormikWizardStepProps
extends FormikWizardContextValue<FormikWizardBaseValues, any> {
step: FormikWizardStepType;
Form?: any;
steps: string[];
FormWrapper: React.SFC<FormikWizardWrapperProps<any>>;
wizard: WizardContext;
formikProps?: Partial<FormikProps<any>>;
onSubmit: FormikWizardProps<any>["onSubmit"];
}
function FormikWizardStep({
step,
FormWrapper,
steps,
wizard,
formikProps,
onSubmit,
setStatus,
status,
values,
setValues
}: FormikWizardStepProps) {
const info = React.useMemo(() => {
return {
canGoBack: steps[0] !== step.id,
currentStep: step.id,
isLastStep: steps[steps.length - 1] === step.id
};
}, [steps, step]);
const handleSubmit = React.useCallback(
async sectionValues => {
setStatus(undefined);
let status;
try {
if (info.isLastStep) {
const newValues = produce(values, (draft: any) => {
draft[info.currentStep] = sectionValues;
});
status = await onSubmit(newValues);
setValues(newValues);
} else {
status = step.onAction
? await step.onAction(sectionValues, values)
: undefined;
setValues((values: any) => {
return produce(values, (draft: any) => {
draft[info.currentStep] = sectionValues;
});
});
setImmediate(wizard.next);
}
} catch (e) {
status = e;
}
setStatus(status);
},
[
info.currentStep,
info.isLastStep,
onSubmit,
setStatus,
setValues,
step,
values,
wizard.next
]
);
return (
<Formik
{...formikProps}
enableReinitialize
initialValues={step.initialValues}
validationSchema={step.validationSchema}
validate={step.validate}
onSubmit={handleSubmit}
>
{props => (
<Form>
<FormWrapper
{...info}
steps={steps}
wizard={wizard}
actionLabel={step.actionLabel}
isSubmitting={props.isSubmitting}
goToPreviousStep={() => {
setStatus(undefined);
if (step.keepValuesOnPrevious) {
setValues((values: any) =>
produce(values, (draft: any) => {
draft[step.id] = props.values;
})
);
}
wizard.previous();
}}
status={status}
values={values}
setStatus={setStatus}
setValues={setValues}
triggerSubmit={() => props.handleSubmit()}
>
{React.createElement(step.component)}
</FormWrapper>
</Form>
)}
</Formik>
);
}
export function FormikWizard<T>({
formikProps,
albusProps,
onSubmit,
steps,
render
}: FormikWizardProps<T>) {
const [status, setStatus] = React.useState(undefined);
const [values, setValues] = React.useState(() => getInitialValues(steps));
React.useEffect(() => {
setValues(getInitialValues(steps));
setStatus(undefined);
}, [steps]);
const stepIds = React.useMemo(() => steps.map(step => step.id), [steps]);
return (
<AlbusWizard {...albusProps}>
<FormikWizardContext.Provider
value={{
status,
setStatus,
values,
setValues
}}
>
<AlbusSteps>
{steps.map(step => (
<AlbusStep
key={step.id}
id={step.id}
render={wizard => (
<FormikWizardStep
wizard={wizard}
formikProps={formikProps}
onSubmit={onSubmit}
steps={stepIds}
status={status}
values={values}
setValues={setValues}
setStatus={setStatus}
step={{
...step,
initialValues: values[step.id] || {}
}}
FormWrapper={render}
/>
)}
/>
))}
</AlbusSteps>
</FormikWizardContext.Provider>
</AlbusWizard>
);
}
export default FormikWizard;
export function useFormikWizard<T>() {
return React.useContext(FormikWizardContext) as FormikWizardContextValue<T>;
}
@zifahm wow, thanks a lot :D
@zaguiini react native has no type="submit" , so how do i got to next step? after clicking the button. Unable to find any albus examples too for submitting.