12

Redux-form "Field" 组件提供onChange 属性。每当从底层输入触发 onChange 事件时将调用的回调。此回调允许获取字段的“newValue”和“previousValue”。

React-final-form "Field" 组件没有这个属性。

那么,我怎样才能获得相同的功能呢?

4

5 回答 5

15

React-final-form 用一个很小的外部包来处理这个功能。

基本上,它是一个附加组件,可以添加到使用其名称绑定到元素的表单中:

<Field name="foo" component="input" type="checkbox" />
<OnChange name="foo">
  {(value, previous) => {
    // do something
  }}
</OnChange>

当前的文档可以在这里找到:

https://github.com/final-form/react-final-form-listeners#onchange

于 2019-06-07T14:13:31.147 回答
11

我没有使用 redux-form,但是我在 Field 组件周围添加了一个超级简单的包装器来监听 onChange,如下所示:

const Input = props => {

    const {
        name, 
        validate, 
        onChange,
        ...rest
    } = props;

    return (
        <Field name={name} validate={validate}>
            {({input, meta}) => {
                return (
                    <input 
                        {...input}
                        {...rest}
                        onChange={(e) => {
                            input.onChange(e); //final-form's onChange
                            if (onChange) { //props.onChange
                                onChange(e);
                            }
                        }}
                    />
            )}}
        </Field>
    );
};
于 2018-09-22T22:22:50.863 回答
10

更改检测下的想法是订阅值更改并在值实际更改时Field调用您的自定义处理程序。onChange我准备了简化的示例,您可以在其中看到它的实际效果。详细信息在MyField.js文件中。

结果,您可以像使用它一样使用它redux-form

<MyField 
  component="input"
  name="firstName"
  onChange={(val, prevVal) => console.log(val, prevVal)}
/>

2022 年 1 月更新

虽然上面的代码仍然有效(检查沙盒版本),但有时解决方案需要更多的时间。

这是一个更新的沙箱,通过钩子实现。它基于一个useFieldValue钩子和OnChange组件作为这个钩子的消费者。但是当您需要重新渲染之间的先前值时,可以单独使用钩子本身。该解决方案不依赖于meta.active该领域。

// useFieldValue.js
import { useEffect, useRef } from "react";
import { useField } from "react-final-form";

const usePrevious = (val) => {
  const ref = useRef(val);

  useEffect(() => {
    ref.current = val;
  }, [val]);

  return ref.current;
};

const useFieldValue = (name) => {
  const {
    input: { value }
  } = useField(name, { subscription: { value: true } });
  const prevValue = usePrevious(value);

  return [value, prevValue];
};

export default useFieldValue;

// OnChange.js
import { useEffect } from "react";
import useFieldValue from "./useFieldValue";

export default ({ name, onChange }) => {
  const [value, prevValue] = useFieldValue(name);

  useEffect(() => {
    if (value !== prevValue) {
      onChange(value, prevValue);
    }
  }, [onChange, value, prevValue]);

  return null;
};

另一个不错的选择是这个答案:https ://stackoverflow.com/a/56495998/3647991

于 2018-05-21T10:36:47.827 回答
3

可以使用字段的parse属性并提供一个函数来满足您对值的需求:

<Field
  parse={value => {
    // Do what you want with `value`
    return value;
  }}
  // ...
/>
于 2019-11-06T19:46:23.263 回答
1

您需要使用该ExternalModificationDetector组件来监听字段组件上的更改,如下所示:

    <ExternalModificationDetector name="abc">
      {externallyModified => (
        <BooleanDecay value={externallyModified} delay={1000}>
          {highlight => (
            <Field
                //field properties here
            />
          )}
        </BooleanDecay>
      )}
    </ExternalModificationDetector>

ExternalModificationDetector通过在组件中 封装一个有状态的Field组件,我们可以监听字段值的变化,并通过知道字段是否处于活动状态,推断出字段值何时因外部影响而发生变化。

Via - React-Final-Form Github Docs


这是React-Final-Form文档中提供的沙盒示例: https ://codesandbox.io/s/3x989zl866

于 2018-05-20T16:34:52.370 回答