简体   繁体   English

如何避免反应 forms 中的数据重复

[英]How to avoid data duplication in react forms

Without using any libraries I am struggling to get a clean code doing a simple form in React.在不使用任何库的情况下,我很难在 React 中获得一个简洁的代码来做一个简单的表单。

Let's say I have假设我有

import React, { useState } from 'react';

export const CreateUserForm = () => {
  const [firstName, setFirstName] = useState('');

  const userAddress = {};

  const handleAddressChange = ({ address, isValid }) => {
    userAddress = { ...address };
  };

  const subscribe = () => {
    createUser({firstName, userAddress}).then((response) => console.log(response));
  };

  return (
    <div>
      <input onChange={setFirstName}></input>
      <AddressForm onChange={handleAddressChange}></AddressForm>
      <button onClick={subscribe}></button>
    </div>
  );
};

Here I am duplicating the address in the CreateUserForm component ( address is managed in the AddressForm state).在这里,我复制了CreateUserForm组件中的addressaddressAddressForm状态下进行管理)。

I could add some props to the AddressForm component, so I would end up with something like that:我可以向AddressForm组件添加一些props ,所以我最终会得到类似的东西:

import React, { useState } from 'react';

export const CreateUserForm = () => {
  const [firstName, setFirstName] = useState('');
  const [address, setAddress] = useState({});

  const handleAddressChange = ({ address, isValid }) => {
    setAddress({ ...address });
  };

  const subscribe = () => {
    createUser({firstName, userAddress}).then((response) => console.log(response));
  };

  return (
    <div>
      <input onChange={setFirstName}></input>
      <AddressForm address={address} onChange={handleAddressChange}></AddressForm>
      <button onClick={subscribe}></button>
    </div>
  );
};

So here I would not duplicate the address but I would render the whole CreateUserForm component each time the address change, am I wrong?所以在这里我不会复制address ,但每次地址更改时我都会渲染整个CreateUserForm组件,我错了吗?

So I feel like neither one of those solution is fine, or am I missing something?所以我觉得这些解决方案都不是很好,还是我错过了什么? The first one seems more natural to me but I kinda duplicate the information..第一个对我来说似乎更自然,但我有点重复信息..

What would be the correct way?正确的方法是什么?

The second option is the correct option as the first likely won't work and if it does then there are some bugs waiting to show themselves if you ever make the CreateUserForm component more complicated.第二个选项是正确的选项,因为第一个选项可能不起作用,如果它起作用,那么如果您使 CreateUserForm 组件更复杂,就会有一些错误等待显示出来。

Option 1 doesn't use state properly and can very easily mess up because the userAddress isn't stateful.选项 1 没有正确使用 state 并且很容易搞砸,因为 userAddress 不是有状态的。 It'll be reset to {} everytime the component re-renders.每次重新渲染组件时,它都会重置为 {}。 In order for the first option to work, you'd need to useRef to set up your address variable.为了使第一个选项起作用,您需要 useRef 来设置您的地址变量。

import React, { useState, useRef } from 'react';

export const CreateUserForm = () => {
  const [firstName, setFirstName] = useState('');

  const userAddress = useRef({});

  const handleAddressChange = ({ address, isValid }) => {
    userAddress.current = { ...address };
  };

  const subscribe = () => {
    createUser({firstName, userAddress: userAddress.current}).then((response) => console.log(response));
  };

  return (
    <div>
      <input onChange={setFirstName}></input>
      <AddressForm onChange={handleAddressChange}></AddressForm>
      <button onClick={subscribe}></button>
    </div>
  );
};

This change to the first option would prevent re-renders at the cost of making the AddressForm much less controlled.对第一个选项的这种更改将防止重新渲染,但代价是使 AddressForm 控制得更少。 It would also prevent you from passing the address down to any other children of the component since they would not re-render because the parent doesn't either unless you change the first name input.它还会阻止您将地址传递给组件的任何其他子级,因为它们不会重新渲染,因为除非您更改名字输入,否则父级也不会重新渲染。

The CreateUserForm component would definitely re-render every time handleAddressChange is called in the second option.每次在第二个选项中调用 handleAddressChange 时,CreateUserForm 组件肯定会重新渲染。 Typically in smaller applications, the re-render will have no issues with performance.通常在较小的应用程序中,重新渲染不会有性能问题。 If you begin to have performance issues, then figure out what children of CreateUserForm take a while to re-render and memoize them (React.Memo or PureComponent) that way the component will re-render quickly.如果您开始遇到性能问题,请找出 CreateUserForm 的哪些子项需要一段时间来重新渲染和记忆它们(React.Memo 或 PureComponent),这样组件将快速重新渲染。 Although memoization requires you to also make sure that what you are passing into the components are referentially stable (ie useCallback and useRef).尽管 memoization 还要求您确保传递给组件的内容在引用上是稳定的(即 useCallback 和 useRef)。

What I usually do to check if a form is rendering quickly enough is to hold down a key on the form inputs and see if it repeats in a non-jerky way.我通常检查表单是否渲染得足够快的方法是按住表单输入上的一个键,看看它是否以非生涩的方式重复。 Although that particular metric is mostly from my ideals and isn't fully necessary for all applications.尽管该特定指标主要来自我的理想,并且并非所有应用程序都完全必要。

I know you were trying to work without a library for the form, but react-hook-form seems to be able to give the range from completely uncontrolled to controlled depending on the purpose to keep up performance and minimize excess re-renders.我知道您试图在没有表单库的情况下工作,但是react-hook-form似乎能够根据目的提供从完全不受控制到受控的范围,以保持性能并最大限度地减少过多的重新渲染。

Second approach is better as you don't have to maintain data in both components (parent and child).第二种方法更好,因为您不必在两个组件(父组件和子组件)中维护数据。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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