@muzikanto/redux-form

Form state manager

Usage no npm install needed!

<script type="module">
  import muzikantoReduxForm from 'https://cdn.skypack.dev/@muzikanto/redux-form';
</script>

README

@muzikanto/redux-form

npm version downloads size dependencies Status Coverage Status type license Code style

Introduction

  • easy migrate to another technology (apollo)
  • partial render form
  • easy create form
  • form validation
  • create form fields
  • create form array fields

Installation

npm i @muzikanto/redux-form
# or
yarn add @muzikanto/redux-form

require react, react-doom, redux, react-redux

Related projects

Package Version Downloads
apollo-form npm version downloads

Examples

Demo

Demo sign in

Demo todo list

Demo with confirm

Show code examples

Learn docs for use this package

Api

First add to a global store

const globalStore = createStore((state, action) => {
   switch (action.type) {
      case 'FORM:UPDATE': {
         return { ...state, [action.form]: { ...action.payload } };
      }
      case 'FORM:DELETE':
         return {
            ...state,
            [action.form]: null,
         };
   }

   return state;
});

create Form

interface State {
   text: string;
   field: string;
   deep: {
      one: string;
      two: string;
   };
   arr: string[];
}

const validationSchema = Yup.object().shape({
   email: Yup.string()
      .required()
      .max(5),
   deep: Yup.object().shape({
      one: Yup.string()
         .required()
         .max(2),
   }),
});

const initialState = {
   email: '1',
   password: '',
   deep: { one: '1' },
   arr: ['', '2', '31'],
};

function Example() {
   return (
      <ReduxForm
         name='test'
         selector={state => state.test}
         // reset form values with current `initialState`
         // please use carefully
         enableReinitialize
         initialState={initialState}
         validationSchema={validationSchema}
         validate={({ values }) => {
            if (values.email === '12') {
               return {
                  email: 'Not 12',
               };
            }

            return undefined;
         }}
         onSubmit={async ({ values }, form) => {
            await wait(1000);
            console.log('submit', values);
            form.reset({
               ...values,
               email: 'Reseted',
            });
         }}
         onChange={(state, form) => console.log('Values: ', state)}
      >
         <FormTextField
            name='email'
            validate={v => {
               if (v.length === 1) {
                  return 'custom error';
               }

               return undefined;
            }}
         />
         <FormTextField name='password' />
         <FormTextField name='deep.one' />
         <FormTextField name='arr.0' />
      </ReduxForm>
   );
}

create field

function FormTextField(props: { name: string; validate?: FieldValidator<string> }) {
   const field = useField(props);

   return <TextField {...getFieldProps(field)} />;
}

// or

function FormTextField(props: { name: string; validate?: FieldValidator<string> }) {
   return (
      <Field<string> name={props.name} validate={props.validate}>
         {({ field }) => {
            const showError = Boolean(!field.focused && field.touched && field.error);

            return (
               <TextField
                  value={field.value}
                  onChange={e => field.setFieldValue(e.target.value)}
                  onFocus={() => field.setFieldFocused()}
                  onBlur={() => field.setFieldTouched(true)}
                  helperText={showError ? field.error : undefined}
                  error={showError}
               />
            );
         }}
      </Field>
   );
}

create array field

function FormTextFieldArray(props: { name: string; validate: FieldValidator<string[]> }) {
   return (
      <FieldArray<string> name={props.name} validate={props.validate}>
         {({ field }) => {
            return (
               <>
                  {field.value.map((el, i) => {
                     return (
                        <Grid item xs={3} key={'arr-field' + i}>
                           <FormTextField
                              key={'test' + i}
                              name={props.name + '.' + i}
                              label={props.name + '.' + i}
                           />
                        </Grid>
                     );
                  })}

                  <Grid item xs={3}>
                     <Box display='flex'>
                        <Button onClick={() => field.push((field.value.length + 1).toString())}>
                           push
                        </Button>
                        <Button onClick={() => field.pop()}>pop</Button>
                     </Box>
                  </Grid>
               </>
            );
         }}
      </FieldArray>
   );
}

create submit button

function FormSubmit() {
   return (
      <Submit>
         {({ isValid, isSubmitted, loading, existsChanges }) => (
            <Button type='submit' disabled={loading || (isSubmitted ? !isValid : false)}>
               Submit
            </Button>
         )}
      </Submit>
   );
}

show error message

function FirstError(props: { name: string; ignoreTouched?: boolean }) {
   return (
      <ErrorMessage
         ignoreTouched={props.ignoreTouched}
         name={props.name}
         children={({ error }) => (
            <span>
               password-err: (<b style={{ color: 'red' }}>{error}</b>)
            </span>
         )}
      />
   );
}

show loader

function CustomLoader() {
   return (
      <FormLoader children={({ loading }) => <span>{loading ? 'loading...' : 'loaded'}</span>} />
   );
}

License

MIT