【问题标题】:How to solve Uncontrolled Component problem in React with Function Component?如何用函数组件解决 React 中的不受控组件问题?
【发布时间】:2021-12-19 06:44:42
【问题描述】:

我正在制作表单组件。(它是功能组件) 它是不受控制的组件,因为我不想在Input 组件中进行不必要的渲染。 但它有一个意想不到的词。

  1. 我尝试在Input 组件中使用setState() 设置值并通过值道具onChange。它不是将整个值从 Input 传递到 Form

  2. 我不想要不必要的渲染。但是,当我在电子邮件中输入值时,会同时使用密码对渲染做出反应。

我该如何解决这个问题?

代码沙盒链接 https://codesandbox.io/s/makewelldonecomponents-txxl0?file=/src/Input.js

或代码

(输入组件)

import React, { useEffect, useState } from "react";

const Input = ({ type, placeholder, onChange }) => {
  const [value, setValue] = useState("");

  function handleChange(e) {
    setValue(e.target.value);
    onChange(value);
  }

  return (
    <>
      {console.log("render", placeholder)}
      <input placeholder={placeholder} value={value} onChange={handleChange} />
    </>
  );
};

export default Input;

(表单组件)

import React, { useState, useEffect } from "react";
import Input from "./Input";

const Form = () => {
  const [email, setEmail] = useState("");
  const [password, setPassword] = useState("");
  const [state, setState] = useState(0);

  function handleSubmit(e) {
    e.preventDefault();
    console.log(email, password);
  }

  function handleEmail(value) {
    setEmail(value);
    console.log(value);
  }

  function handlePassword(value) {
    setPassword(value);
  }

  function handleReset(e) {
    setEmail("");
    setPassword("");
    setState(state + 1);
  }

  return (
    <form onSubmit={handleSubmit}>
      <Input
        key={state + "email"}
        type="email"
        placeholder="이메일"
        onChange={handleEmail}
      />
      <Input
        key={state + "password"}
        type="password"
        placeholder="비밀번호"
        onChange={handlePassword}
      />
      <button type="submit">가입</button>
      <button type="button" onClick={handleReset}>
        초기화
      </button>
    </form>
  );
};

export default Form;

【问题讨论】:

    标签: reactjs react-functional-component


    【解决方案1】:
    1. Input 组件中使用useRef 而不是useState
    import React, { useRef } from "react";
    
    const Input = ({ type, placeholder, onChange }) => {
      const valRef = useRef("");
    
      function handleChange(e) {
        valRef.current = e.target.value;
        onChange(valRef.current);
      }
    
      return (
        <>
          {console.log("render", placeholder)}
          <input
            placeholder={placeholder}
            value={valRef.current}
            onChange={handleChange}
          />
        </>
      );
    };
    
    export default Input;
    
    
    1. 使用useCallbackhandleEmailhandlePassword 函数
    
      const handleEmail = useCallback((value) => {
        setEmail(value);
        console.log(value);
      }, []);
    

    【讨论】:

    • 感谢您的回答。我还有一个问题。当我第一次渲染组件时,useCallback 只渲染了一次。正确的?所以,你回答 Q2。但是,我用 useCallback 重写了我的代码,但在 handleEmail、handlePassword 中仍然是不必要的渲染。这是不可避免的工作吗?
    【解决方案2】:

    您可以在 React 中实现不受控制的表单,而无需使用状态和多个更改处理程序。

    这是更新后的沙盒:

    Form组件:

    const Form = () => {
      const email = useRef(null);
      const password = useRef(null);
    
      function handleSubmit(e) {
        e.preventDefault();
        console.log(email.current.value, password.current.value);
      }
    
      return (
        <form onSubmit={handleSubmit}>
          <Input type="email" placeholder="이메일" ref={email} />
          <Input type="password" placeholder="비밀번호" ref={password} />
          <button type="submit">가입</button>
          <button type="reset">초기화</button>
        </form>
      );
    };
    
    export default Form;
    

    Input组件:

    import React, { forwardRef } from "react";
    
    const Input = forwardRef((props, ref) => {
      return <input {...props} ref={ref} />;
    });
    

    【讨论】:

    • 好答案。但是,我需要了解 Q2。当我输入电子邮件或密码时,如何知道只渲染一个组件?
    • @Aaaaaa 在上面的实现中,输入电子邮件/密码时没有重新渲染任何输入组件
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-01-08
    相关资源
    最近更新 更多