【问题标题】:redux form component not reflecting store stateredux 表单组件不反映商店状态
【发布时间】:2017-06-14 20:10:27
【问题描述】:

我创建了一个非常简单的 yes/no 组件,它使用 redux 形式映射到 true/false 值。 单击“否”时,商店中的值会更新,但组件不会更新。 只有先单击“是”后,组件才会在单击“否”时更新。

我在这里做错了什么?为什么 store 中的状态没有反映在组件中?
请注意,对于我的用例而言,重要的是最初没有单击任何按钮。

沙盒:

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);

【问题讨论】:

  • 能不能不保持这样 input.value == x.value ?
  • @VivekN 不,我在我的问题中指出了为什么不
  • 确实它与true/false 值有关。如果将它们替换为ab,它会按预期工作。我对 redux-form 不是很熟悉,但文档可能会解释这一点。
  • 因为 false 值和再次单击 No 时,该值变成了 false,就像它最初是一个空字符串一样,我假设 redux-form 将其视为 false。因为状态确实不改变,这就是为什么不重新渲染。
  • @WillemD'Haeseleer 而不是真假值,你能把它们保持为是或否

标签: javascript reactjs react-redux react-redux-form


【解决方案1】:

IDK 正是 redux-form 的工作原理,但是您在未定义的初始状态和错误值方面遇到了一些问题; 使用format 你可以处理这个

https://codesandbox.io/s/BL50OzNZY

     format={(value) => value}

只返回值,无需额外检查。

【讨论】:

  • 这很好奇,因为您的函数实际上并没有做任何事情。添加格式化程序本身似乎具有解决问题的副作用。
  • 没错.. 不需要那个 IF,只是返回值本身会覆盖其他一些排除您的虚假值的验证..
  • 它工作得很好,但现在每个使用我的组件的人都需要包含一个不做任何事情的神秘格式化程序。不是一个令人愉快的解决方案。
【解决方案2】:

我认为原因是在 redux-form 代码的某个地方,它最初将空字符串和 false 视为同一件事,并且不会触发重新渲染。看起来 redux-form 使用了这个 deepEquals 函数定制器:

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
}

您可以尝试自己将初始值设置为 false,看看它是否能解决您的问题。

【讨论】:

【解决方案3】:

发生这种情况是因为您的字段“myButton”的初始状态等于“”,当您单击“否”按钮时,状态更改为 false,但由于新状态等于前一个状态(“”== false ) 组件不会重新渲染。

您可以通过为您的组件传递一些不同于您的选项(true 和 false)的初始状态来解决此问题。例如,您可以将初始状态设置为任何字符串:

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

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

【讨论】:

  • notTrueOrFalse 初始化了store,我相信这并不理想。
  • 我很欣赏这行得通,但它似乎不是一个很好的解决方案。除了初始化表单之外,在提交表单时,我还必须添加额外的逻辑来删除那个无用的值。我只想保留一个布尔值。
  • @WillemD'Haeseleer 我相信您已经需要添加一些额外的逻辑,因为您的组件可以为您提供三个可能的值:true、false、“”。也许将组件的初始值默认设置为 true 或 false 是有意义的。
  • 组件的初始状态应该是未选中的。该值可以是真、假或未定义,三个不同的值是。我也愿意接受第三个状态为空的解决方案,或者在最坏的情况下,一个空字符串。但没有其他值。
猜你喜欢
  • 2019-10-06
  • 1970-01-01
  • 1970-01-01
  • 2016-06-25
  • 2018-09-01
  • 2018-11-30
  • 2016-06-07
  • 2021-11-16
  • 2019-07-15
相关资源
最近更新 更多