Skip to content

Latest commit

 

History

History
795 lines (594 loc) · 29.8 KB

actions.md

File metadata and controls

795 lines (594 loc) · 29.8 KB

Action Creators

Model Action Creators

All model and field action creators can be imported via import { actions } from 'react-redux-form'. The action thunk creators require redux-thunk middleware to work, as they use thunks to get the current model state.

Also, all action creators are trackable, which means that the model argument can be a function, such as track(), that returns a string model path given the store's state. For example:

import { track, actions } from 'react-redux-form';

// this will dispatch a change() action for the
// user's goat with id === 123
dispatch(actions.change(
  track('user.goats[].color', {id: 123}),
  'black'));

actions.change(model, value, [options])

Returns an action that, when handled by a modelReducer, changes the value of the model to the value.

When the change action is handled by a formReducer, the field model's .dirty state is set to true and its corresponding .pristine state is set to false.

Note: if using track, redux-thunk is required.

Arguments

  • model (String | Function): the model whose value will be changed
  • value (any): the value the model will be changed to
  • options (object): an object containing options for the action creator:

Options

  • .silent (boolean): if true, the CHANGE action will not trigger change-related operations in the form reducer, such as setting .pristine = false. Default: false

Example

import {
  modelReducer,
  actions
} from 'react-redux-form';

const userReducer = modelReducer('user');

const initialState = { name: '', age: 0 };

userReducer(initialState, actions.change('user.name', 'Billy'));
// => { name: 'Billy', age: 0 }

Notes

  • The model path can be as deep as you want. E.g. actions.change('user.phones[0].type', 'home')

actions.reset(model)

Returns an action that, when handled by a modelReducer, changes the value of the respective model to its initial value.

Arguments

  • model (String | Function): the model whose value will be reset to its initial value.

Example

import {
  modelReducer,
  actions
} from 'react-redux-form';

const initialState = { count: 10 };

const counterReducer = modelReducer('counter', initialState);

const nextState = counterReducer(initialState,
  actions.change('counter.count', 42));
// => { count: 42 }

const resetState = counterReducer(nextState,
  actions.reset('counter.count'));
// => { count: 10 }

Notes

  • This action will reset both the model value in the model reducer, and the model field state in the form reducer (if it exists).
  • To reset just the field state (in the form reducer), use actions.setInitial(model).

actions.merge(model, values)

Dispatches an actions.change(...) action that merges the values into the value specified by the model.

Arguments

  • model (String | Function): the model to be merged with values.
  • values (Object | Object[] | Objects...): the values that will be merged into the object represented by the model.

Notes

  • Use this action to update multiple and/or deep properties into a model, if the model represents an object.
  • This uses icepick.merge(modelValue, values) internally.

actions.xor(model, item)

Dispatches an actions.change(...) action that applies an "xor" operation to the array represented by the model; that is, it "toggles" an item in an array.

If the model value contains item, it will be removed. If the model value doesn't contain item, it will be added.

Arguments

  • model (String | Function): the array model where the xor will be applied.
  • item (any): the item to be "toggled" in the model value.

Example

import { actions } from 'react-redux-form';

// assume user.numbers = [1, 2, 3, 4, 5]

dispatch(actions.xor('user.numbers', 3));
// user.numbers = [1, 2, 4, 5]

dispatch(actions.xor('user.numbers', 6));
// user.numbers = [1, 2, 4, 5, 6]

Notes

  • This action is most useful for toggling a checkboxes whose values represent items in a model's array.

actions.push(model, item)

Dispatches an actions.change(...) action that "pushes" the item to the array represented by the model.

Arguments

  • model (String | Function): the array model where the item will be pushed.
  • item (any): the item to be "pushed" in the model value.

Notes

  • This action does not mutate the model. It only simulates the mutable .push() method.

actions.toggle(model)

Dispatches an actions.change(...) action that sets the model to true if it is falsey, and false if it is truthy.

Arguments

  • model (String | Function): the model whose value will be toggled.

Notes

  • This action is most useful for single checkboxes.

actions.filter(model, iteratee)

Dispatches an actions.change(...) action that filters the array represented by the model through the iteratee function.

If no iteratee is specified, the identity function is used by default.

Arguments

  • model (String | Function): the array model to be filtered.
  • iteratee (Function): the filter iteratee function that filters the array represented by the model.
    • default: identity (a => a)

actions.map(model, iteratee)

Dispatches an actions.change(...) action that maps the array represented by the model through the iteratee function.

If no iteratee is specified, the identity function is used by default.

Arguments

  • model (String | Function): the array model to be mapped.
  • iteratee (Function): the map iteratee function that maps the array represented by the model.

actions.remove(model, index)

Dispatches an actions.change(...) action that removes the item at the specified index of the array represented by the model.

Arguments

  • model (String | Function): the array model to be updated.
  • index (Number): the index that should be removed from the array.

actions.move(model, fromIndex, toIndex)

Dispatches an actions.change(...) action that moves the item at the specified fromIndex of the array to the toIndex of the array represented by the model.

If fromIndex or toIndex are out of bounds, an error will be thrown.

Arguments

  • model (String | Function): the array model to be updated.
  • fromIndex (Number): the index of the item that should be moved in the array.
  • toIndex (Number): the index to move the item to in the array.

Example

// Assuming this state:
// {
//  foo: {
//     bar: [1, 2, 3, 4]
//   }
// }

dispatch(actions.move('foo.bar', 2, 0));
// the new foo.bar state:
// => [3, 1, 2, 4]

actions.load(model, value)

Dispatches an actions.change(...) action that loads (updates) the model with value silently. It does not trigger any effects of a CHANGE action in the form reducer.

It also sets the .loadedValue of the model's field to the dispatched value.

Arguments

  • model (String | Function): the model whose value will be changed
  • value (any): the value to load (update) the model with

Notes

  • This action is useful when you need to set an initial model value asynchronously.
  • If the initial model value is available at runtime, prefer setting it as part of the initialState of the modelReducer instead.
  • This is different than calling actions.change(model, value, { silent: true }). Both are similar with one main difference: actions.load also updates the .loadedValue, whereas a silent change does not.

actions.omit(model, props)

Dispatches an actions.change(...) action with the model value updated to not include any of the omitted props.

Arguments

  • model (String | Function): the model to be modified with the omitted props
  • props (String | String[]): the props to omit from the model value

Example

// Assuming this state:
// {
//   test: {
//     foo: 1,
//     bar: 2,
//     baz: 3
//   }
// }

dispatch(actions.omit('test', 'foo'));
// the new test state:
// => { test: { bar: 2, baz: 3 } }

dispatch(actions.omit('test', ['foo', 'baz']);
// the new test state:
// => { test: { bar: 2 } }

Field Action Creators

All model and field actions can be imported via import { actions } from 'react-redux-form'.

actions.focus(model)

Returns an action that, when handled by a formReducer, changes the .focus state of the field model in the form to true.

The "focus" state indicates that the field model is the currently focused field in the form.

Arguments

  • model (String | Function): the model indicated as focused

Example

import { actions } from 'react-redux-form';

// in a connect()-ed component:
const Newsletter = (props) => {
  const { newsletterForm, dispatch } = props;

  return <form>
    <input type="email"
      onFocus={() => dispatch(actions.focus('newsletter.email'))} />
    { newsletterForm.fields.email.focus &&
      <div>Sweet, you're signing up!</div>
    }
  </form>;
}

Notes

  • If possible, RRF will actually call .focus() on the DOM node if it is focusable.

actions.blur(model)

Returns an action that, when handled by a formReducer, changes the .focus state to false. It also indicates that the field model has been .touched, and will set that state to true.

A "blurred" field indicates that the field model control is not currently focused.

Arugments

  • model (String | Function): the model indicated as blurred (not focused)

actions.setPristine(model)

Returns an action that, when handled by a formReducer, changes the .pristine state of the field model in the form to true.

The "pristine" state indicates that the user has not changed the value of this model yet.

Arguments

  • model (String | Function): the model indicated as pristine

Notes

  • Whenever a field is set to pristine, the entire form is set to:
    • pristine if all other fields are pristine
    • otherwise, dirty.

actions.setDirty(model)

Returns an action that, when handled by a formReducer, changes the .pristine state to false.

A "dirty" field indicates that the model value has been changed, and is no longer pristine.

Arguments

  • model (String | Function): the model indicated as not pristine (dirty)

Notes

  • Whenever a field is set to not pristine (dirty), the entire form is set to not pristine (dirty).

actions.setPending(model, [pending])

Returns an action that, when handled by a formReducer, changes the .pending state of the field model in the form to true. It simultaneously sets the .submitted state to false.

Arguments

  • model (String | Function): the model indicated as pending
  • pending (Boolean): whether the model is pending (true) or not (false).
    • default: true

Notes

  • This action is useful when asynchronously validating or submitting a model. It represents the state between the initial and final state of a field model's validation/submission.

actions.setTouched(model)

Returns an action that, when handled by a formReducer, changes the .touched state of the field model in the form to true. It simultaneously sets the .untouched state to false.

The "touched" state indicates that this model has been focused and then blurred.

Arguments

  • model: (String) the model indicated as touched

Notes

  • Setting a model to touched also sets the entire form to touched.
  • Touched also sets the model to not focused (blurred).

actions.setUntouched(model)

Returns an action that, when handled by a formReducer, changes the .touched state to false.

An "untouched" field indicates that this model has not been focused and blurred yet.

Arguments

  • model (String | Function): the model indicated as not touched (untouched)

Notes

  • This action is useful for conditionally displaying error messages based on whether the field has been touched.

actions.submit(model, [promise])

Waits for a submission promise to be completed, then, if successful:

  • Sets .submitted property of form for model to true
  • Sets .validity property of form for model to the response (or true if the response is undefined).

If the promise fails, the action will:

  • set .submitFailed property of form for model to true
  • set .errors property of form for model to the response

If a promise is not provided, e.g.: actions.submit('user'), then dispatching the action will trigger a <Form> with the specified model to call its onSubmit handler.

Arguments

  • model (String | Function): the model to be submitted
  • promise (Promise): the promise that the submit action will wait to be resolved or rejected
    • default: undefined - will trigger a submit in the <Form> component with the specified model.
  • options (Object): submit options:

Options

  • .validate (Boolean): if true (default), will only submit the form if the form is valid. Default: true
  • .validators or .errors (Object|Function): will first validate the form against the .validators or the .errors (error validators).
    • If valid, the action will set the model's validity and proceed to submit the form.
    • If invalid, the action will set the model's validity and not submit the form.

Example

import { actions } from 'react-redux-form';

// somewhere with dispatch()

// promise
const postUser = api.post({/* user data */})
  // API success
  .then(() => true) // validity = true
  // API failure
  .catch((err) => err) // errors = err

dispatch(actions.submit('user', postUser));

actions.submitFields(model, promise)

Waits for a submission promise to be completed, then, if successful:

  • Sets .submitted property of form for model to true
  • Each key in the response, which represents a sub-model (e.g., "name" for users.name) will have its .validity set to its value.

If the promise fails, the action will:

  • set .submitFailed property of form for model to true
  • Each key in the response, which represents a sub-model (e.g., "name" for users.name) will have its .errors set to its value. (See example)

Arguments

  • model (String | Function): the model to be submitted
  • promise (Promise): the promise that the submit action will wait to be resolved or rejected
  • options (Object): submit options (see actions.submit)

Example

import { actions } from 'react-redux-form';

// somewhere with dispatch()

// promise
const postUser = api.post({/* user data */})
  // API success
  .then(() => true) // validity = true
  // API failure
  .catch((err) => err) // errors = err

// Assume the API (or promise) returns these errors:
// {
//  "email": ["This email is already taken."],
//  "phone": ["Invalid area code.", "Invalid format."],
// }

dispatch(actions.submitFields('user', postUser));

// The errors for `user.email` and `user.phone` will be set
// to the above values.

actions.setSubmitted(model, [submitted])

Returns an action that, when handled by a formReducer, changes the .submitted state of the field model in the form to submitted (true or false). It simultaneously sets the .pending state to the inverse of submitted.

The "submitted" state indicates that this model has been "sent off," or an action has been completed for the model.

Arguments

  • model (String | Function): the model indicated as submitted
  • submitted (Boolean): whether the model has been submitted (true) or not (false).
    • default: true

Example

import { actions } from 'react-redux-form';

// action thunk creator
export default function submitUser(data) {
  return (dispatch) => {
    dispatch(actions.setPending('user', true));

    fetch('...', { body: data })
      .then((response) => {
        // handle the response, then...
        dispatch(actions.setSubmitted('user', true));
      });
  }
}

Notes

  • Use the setPending() and setSubmitted() actions together to update the state of the field model during some async action.

actions.setSubmitFailed(model)

Returns an action that, when handled by a formReducer, changes the .submitFailed state of the field model in the form to true. It simultaneously sets the .pending state to false, and the .retouched state to false.

Arguments

  • model (String | Function): the model indicated as having failed a submit

Notes

  • If the form has not been submitted yet, .submitFailed = false
  • If submitting (pending), .submitFailed = false
  • If submit failed, .submitFailed = true
  • If resubmitting, .submitFailed = false again.

actions.setInitial(model)

Returns an action that, when handled by a formReducer, changes the state of the field model in the form to its initial state.

Here is the default initial field state:

const initialFieldState = {
  focus: false,
  pending: false,
  pristine: true,
  submitted: false,
  touched: false,
  valid: true,
  validating: false,
  viewValue: null,
  validity: {},
  errors: {},
};

Arguments

  • model (String | Function): the model to be reset to its initial state

Notes

  • This action will reset the field state, but will not reset the model value in the model reducer. To reset both the field and model, use actions.reset(model).

Validation Action Creators

actions.setValidity(model, validity, [options])

Returns an action that, when handled by a formReducer, changes the .valid state of the field model in the form to true or false, based on the validity (see below). It will also set the .validity state of the field model to the validity.

It also sets the .errors on the field model to the inverse of the validity.

Arguments

  • model (String | Function): the model whose validity will be set
  • validity (Boolean | Object): a boolean value or an object indicating which validation keys of the field model are valid.
  • options (Object): an object containing options for the action creator:

Options

  • .errors (Boolean): if true, the validity will be set for .errors instead of .validity on the field. This is equivalent to actions.setErrors().

Example

import { actions } from 'react-redux-form';

// somewhere with dispatch():
dispatch(actions.setValidity('user.email', true));

// email field:
// {
//   valid: true,
//   validity: true,
//   errors: false
// }

const val = 'testing123';

dispatch(actions.setValidity('user.password', {
  required: val && val.length,
  correct: val === 'hunter2'
}));

// password field:
// {
//   valid: false,
//   validity: { required: true, correct: false },
//   errors: { required: false, correct: true }
// }

Notes

  • If you really want to set error messages instead, use actions.setErrors(model, errors).
  • Since arrays are objects, the validity argument can be an array. Only do this if your use case requires it.

actions.setFieldsValidity(model, fieldsValidity)

Returns an action that, when handled by a formReducer, sets the .validity state of each sub-model key in the fieldsValidity object to that key's value.

It simultaneously sets the .errors on each sub-model to the inverse of its validity.

Arguments

  • model (String | Function): the model whose sub-model's validities will be set
  • fieldsValidity (Object): an object whose keys are sub-models (e.g., 'name' for user.name) and whose values are the validities for each sub-model.

actions.validate(model, validators)

Returns an action thunk that calculates the validity of the model based on the function/object validators. Then, the thunk dispatches actions.setValidity(model, validity).

A validator is a function that returns true if valid, and false if invalid.

Arguments

  • model (String | Function): the model whose validity will be calculated
  • validators (Function | Object): a validator function or an object whose keys are validation keys (such as 'required') and values are validators.

Example

import { actions } from 'react-redux-form';

const isEmail = (value) => // ... check if email is valid

// assume user.email = "foo@gmail"

// somewhere with dispatch():
dispatch(actions.validate('user.email', isEmail));
// will dispatch actions.setValidity('user.email', false)

dispatch(actions.validate('user.email', {
  isEmail,
  available: (email) => email !== '[email protected]'
});
// will dispatch actions.setValidity('user.email', {
//  isEmail: false,
//  available: true
// });

actions.asyncSetValidity(model, asyncValidator)

Returns an action thunk that calculates the validity of the model based on the async function asyncValidator. That function dispatches actions.setValidity(model, validity) by calling done(validity).

Arguments

  • model (String | Function): the model whose validity will asynchronously be set
  • asyncValidator(value, done) (Function): a function that is given two arguments:
    • value - the value of the model
    • done - the callback where the calculated validity is passed in as the argument.

Example

import { actions } from 'react-redux-form';

// async function
function isEmailAvailable(email, done) {
  fetch('...', { body: email })
    .then((response) => {
      done(response); // true or false
    });
}

// somewhere with dispatch():
dispatch(actions.asyncSetValidity('user.email', isEmailAvailable));
// => 1. will set .pending to true, then eventually...
// => 2. will set .validity to response and .pending to false

Notes

  • This action is useful for general-purpose asynchronous validation using callbacks. If you are using promises, using actions.submit(model, promise) is a simpler pattern.

actions.setErrors(model, errors)

Returns an action that, when handled by a formReducer, changes the .valid state of the field model in the form to true or false, based on the errors (see below). It will also set the .errors state of the field model to the errors.

It simultaneously sets the .validity on the field model to the inverse of the errors.

Arguments

  • model (String | Function): the model whose validity will be set
  • errors (Boolean | Object | String): a truthy/falsey value or an object indicating which error keys of the field model are invalid.

Example

import { actions } from 'react-redux-form';

// somewhere with dispatch():
dispatch(actions.setErrors('user.email', true));

// email field:
// {
//   valid: false,
//   validity: false,
//   errors: true
// }

dispatch(actions.setErrors('user.email', 'So many errors!'));

// email field:
// {
//   valid: false,
//   validity: false,
//   errors: 'So many errors!'
// }

const val = 'testing123';

dispatch(actions.setErrors('user.password', {
  empty: !(val && val.length) && 'Password is required!',
  incorrect: val !== 'hunter2' && 'The password is wrong'
}));

// password field:
// {
//   valid: false,
//   errors: { empty: false, incorrect: 'The password is wrong' }
// }

Notes

  • If you aren't hard-coding error messages, use actions.setValidity(model, validity) instead. It's a cleaner pattern.
  • You can set errors to a boolean, object, array, string, etc. Remember: truthy values indicate errors in errors.

actions.setFieldsErrors(model, fieldsErrors)

Returns an action that, when handled by a formReducer, sets the .errors state of each sub-model key in the fieldsErrors object to that key's value.

It simultaneously sets the .validity on each sub-model to the inverse of its errors.

Arguments

  • model (String | Function): the model whose sub-models validities will be set
  • fieldsErrors (Object): an object whose keys are sub-models (e.g., 'name' for user.name) and whose values are the errors for each sub-model.

actions.validateErrors(model, errorValidators)

Returns an action thunk that calculates the errors of the model based on the function/object errorValidators. Then, the thunk dispatches actions.setErrors(model, errors).

An error validator is a function that returns true or a truthy value (such as a string) if invalid, and false if valid.

Arguments

  • model (String | Function): the model whose validity will be calculated
  • errorValidators (Function | Object): an error validator or an object whose keys are error keys (such as 'incorrect') and values are error validators.

Example

import { actions } from 'react-redux-form';
import { isEmail } from 'validator';

// assume user.email = "foo@gmail"

// somewhere with dispatch():
dispatch(actions.validateErrors('user.email', (val) => {
  return !isEmail(val) && 'Not an email!'
}));
// will dispatch actions.setErrors('user.email', 'Not an email!')

dispatch(actions.validateErrors('user.email', {
  notAnEmail: (val) => !isEmail(val) && 'Not an email!',
  unavailable: (email) => email == '[email protected]' && 'Use a different email'
});
// will dispatch actions.setErrors('user.email', {
//  notAnEmail: 'Not an email!',
//  unavailable: false
// });

Notes

  • As previously stated, if you aren't using error messages, use actions.validate(model, validators) as a cleaner pattern.

actions.validateFields(model, fieldValidators)

Returns an action thunk that calculates the validity for each sub-model key of the fieldValidators object based on the value, which is a validator. Then, the thunk dispatches actions.setValidity(model, validity) for all of the sub-models.

A validator is a function that returns true or a truthy value (such as a string) if valid, and false if invalid.

Arguments

  • model (String | Function): the model whose validity will be calculated
  • fieldValidators (Object): an object whose keys are sub-models, and whose values are validators for each sub-model (see example).

Example

import { actions } from 'react-redux-form';
import { isEmail } from 'validator';

const required = (val) => !!(value && value.length);

dispatch(actions.validateFields('user', {
  email: {
    isEmail,
    required,
  },
  username: {
    goodLength: (val) => val.length <= 8,
  },
}));

actions.validateFieldsErrors(model, fieldErrorsValidators)

Returns an action thunk that calculates the errors for each sub-model key of the fieldErrorsValidators object based on the value, which is an errorValidator. Then, the thunk dispatches actions.setErrors(model, errors) for all of the sub-models.

An error validator is a function that returns true or a truthy value (such as a string) if invalid, and false if valid.

Arguments

  • model (String | Function): the model whose errors will be calculated
  • fieldErrorsValidators (Object): an object whose keys are sub-models, and whose values are error validators for each sub-model (see example).

Example

import { actions } from 'react-redux-form';
import { isEmail } from 'validator';

dispatch(actions.validateFieldsErrors('user', {
  email: {
    isMissing: (val) => !val || !val.length,
    invalidEmail: (val) !isEmail(val),
  },
  username: {
    tooLong: (val) => val.length > 8,
  },
}));

actions.resetValidity(model, [omitKeys])

Resets the .validity and .errors for the field model to the .validity and .errors of the initial field state.

If omitKeys is specified as an array, it will only reset the validity to the omitted keys by removing them from the current validity/errors.

Alias: actions.resetErrors(model)

Arguments

  • model (String | Function): the model whose validity and errors will be reset.
  • omitKeys (Array): the keys to reset by omitting them. Default: false (will reset all keys)