简体   繁体   中英

redux form component not reflecting store state

I created a very simple yes / no component mapped to true / false values with redux form. When clicking "No" the value is updated in the store, but the component does not update. Only after clicking Yes first the component updates when clicking No.

What am I doing wrong here ? why is the state in the store not reflected in the component ?
Note that it's important for my use case that initially, no button is clicked.

sandbox:

https://codesandbox.io/s/r06VKjB4K

import React from 'react';
import { Field, reduxForm } from 'redux-form';

const buttonStyle = {
  width: '50px',
  display: 'inline-block',
  border: '1px solid green',
  margin: '5px',
  padding: '5px',
  cursor: 'pointer',
  textAlign: 'center',
};

const ButtonBar = ({ options, input }) =>
  <div style={{ display: 'block' }}>
    {options.map(x =>
      <div
        onClick={() => {
          input.onChange(x.value);
        }}
        style={{
          ...buttonStyle,
          ...{
            backgroundColor: input.value === x.value ? x.selected : 'white',
          },
        }}
      >
        {x.displayName}
      </div>,
    )}
  </div>;

const SimpleForm = props => {
  return (
    <form>
      <div style={{ display: 'inline-block', border: '1px solid grey' }}>
        <Field
          name="myButton"
          component={ButtonBar}
          options={[
            {
              value: true,
              displayName: 'Yes',
              selected: 'green',
            },
            {
              value: false,
              displayName: 'No',
              selected: 'red',
            },
          ]}
        />
      </div>
    </form>
  );
};

export default reduxForm({
  form: 'simple', // a unique identifier for this form
})(SimpleForm);

IDK exactly how redux-form works but you are having some issues regarding undefined initial state and false values; Using format you can handle that

https://codesandbox.io/s/BL50OzNZY

     format={(value) => value}

Just returns the value, no additional checks necessary.

I think the reason is that somewhere in the redux-form code, it treats the empty string and false as the same thing initially and does not trigger a rerender. It looks like redux-form uses this deepEquals function customizer:

const customizer = (obj, other) => {
  if (obj === other) return true
  if (
    (obj == null || obj === '' || obj === false) &&
    (other == null || other === '' || other === false)
  )
    return true

  if (obj && other && obj._error !== other._error) return false
  if (obj && other && obj._warning !== other._warning) return false
}

You could try setting the initial value to false yourself to see if it fixes your problem.

It is happening because your Field "myButton" has initial state equal to "" and when you click on the "No" button the state changes to false but since the new state equals to the previous one("" == false) the component does not re-render.

You can fix this issue passing some initial state for your component which is different from you options(true and false). For example you can set the initial state as any string:

<SimpleForm
    initialValues={{ myButton: 'notTrueOrFalse' }}
    onSubmit={showResults}
  />

https://codesandbox.io/s/0R1rw63nV

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM