Reactjs 如何使用钩子通过一个事件处理函数动态更新任何输入字段的值

Reactjs 如何使用钩子通过一个事件处理函数动态更新任何输入字段的值,reactjs,react-hooks,controlled-component,Reactjs,React Hooks,Controlled Component,TL;DR 有没有办法用一个事件动态更新输入字段的值 处理函数就像我们可以处理有状态组件一样 this.state = { email : "", password : "" } const handleChange = e => { const {name , value} = e.target this.setState({ [name] : value })

TL;DR

有没有办法用一个事件动态更新输入字段的值 处理函数就像我们可以处理有状态组件一样

    this.state = {
      email : "",
      password : ""
    }

    const handleChange = e => {
        const {name , value} = e.target
        this.setState({
           [name] : value
        })
    }
我正在处理一个带有2个字段的登录表单。电子邮件和密码。当我使用表示两个字段的2 useState时,当我使用handleChange更新状态时,两个状态都得到更新。这不是我们的意图

   const [email, setEmail] = useState()
   const [password, setPassword] = useState()

    const handleChange = e => {
        const {value} = e.target
        setEmail(value)
        setPassword(value)
    }
我不想使用多个事件处理程序来处理每个输入字段。我试过这个

    const [state , setState] = useState({
        email : "",
        password : ""
    })

    const handleChange = e => {
        const {name , value} = e.target
        setState({
            [name] : value
        })
    }
但这会一次更新一个属性。另一个属性值丢失。那么,有没有办法像有状态组件一样,用一个事件处理函数更新所有输入字段呢

    this.state = {
      email : "",
      password : ""
    }

    const handleChange = e => {
        const {name , value} = e.target
        this.setState({
           [name] : value
        })
    }

您应该将setState与回调函数一起使用:

setState(prev => ({ 
    ...prev,
    email: 'new mail',
}))
您将创建一个新的状态对象,该对象是由以前的状态创建的。你可以覆盖任何你需要的东西。 如果你有一个复杂的状态对象,你需要更多的新对象

试试看

此.state={ 电邮:“, 密码:“ }


您可以创建一个自定义挂钩,如下所示:

import { useState } from 'react';

export const useForm = (initialValues) => {
  const [values, setValues] = useState(initialValues);

  return {
    values,
    handleChange: (e) => {
      setValues({
        ...values,
        [e.target.name]: e.target.value,
      });
    },
    reset: () => setValues(initialValues),
  };
};
然后以任何形式使用它(例如):

导出默认函数SignInfo(){
const{values,handleChange,reset}=useForm({用户名:'',密码:'});
常量handleSubmit=e=>{
e、 预防默认值();
重置();
};
返回(
登录
);
}

多亏了多安·阿拉巴奇。我试图模仿基于类的组件的state和setState,这样感觉就不会改变。我的解决方案是这样的

const [state , setState] = useState({
    email : "",
    password : ""
})

const handleChange = e => {
    const {name , value} = e.target
    setState( prevState => ({
        ...prevState,
        [name] : value
    }))
}

您可以使用react提供的UseReducer。它非常简单,并且提供了非常干净的代码

import React, {useReducer} from 'react';

const initialState = {
    email: '',
    password: ''
};

function reducer(state, action) {
    switch (action.type) {
        case 'email':
            return {
                ...state,
                email: action.payload
            };
        case 'password':
            return {
                ...state,
                password: action.payload
            };
        default:
            throw new Error();
    }
}

const Login = () => {
    const [state, dispatch] = useReducer(reducer, initialState);
    const handleChange = event => dispatch({ type: event.target.name, payload: event.target.value.trim() });
    return (
        <div className="container">
            <div className="form-group">
                <input 
                    type="email"
                    name="email"
                    value={state.email}
                    onChange={handleChange}
                    placeholder="Enter Email"
                />
            </div>
            <div className="form-group">
                <input 
                    type="password"
                    name="password"
                    value={state.password}
                    onChange={handleChange}
                    placeholder="Enter Password"
                />
            </div>
            <div className="form-group">
                <button className="btn btn-info">Login</button>
            </div>
        </div>
    )
}

export default Login;
import React,{useReducer}来自“React”;
常量初始状态={
电子邮件:“”,
密码:“”
};
功能减速机(状态、动作){
开关(动作类型){
“电子邮件”案例:
返回{
……国家,
电子邮件:action.payload
};
案例“密码”:
返回{
……国家,
密码:action.payload
};
违约:
抛出新错误();
}
}
常量登录=()=>{
const[state,dispatch]=useReducer(reducer,initialState);
const handleChange=event=>dispatch({type:event.target.name,payload:event.target.value.trim()});
返回(
登录
)
}
导出默认登录;
您可以使用prevState

const [state, setState] = useState({ fruit: "", price: "" });

  const handleChange = e => {
    const { name, value } = e.target;
    setState(prevState => ({
      ...prevState,
      [name]: value
    }));
  };

<input
        value={state.fruit}
        type="text"
        onChange={handleChange}
        name="fruit"
      />
      <input
        value={state.price}
        type="text"
        onChange={handleChange}
        name="price"
      />
const[state,setState]=useState({fruit:,price:});
常量handleChange=e=>{
常量{name,value}=e.target;
设置状态(prevState=>({
…国家,
[名称]:值
}));
};
试试这个:

  const [email, setEmail] = useState('')
  const [password, setPassword] = useState('')

    const handleChange = (name, e) => {
      switch (name) {
      case 'email':
        setEmail(e);
        break;
      case 'password':
        setPassword(e);
         break;
       default:
       break;
    }
  };
你的意见:

<input
    type="text"
    onChange={ e => handleChange('email',e)}
    name="email"
  />
<input
    type="text"
    onChange={ e => handleChange('password',e)}
    name="password"
  />
handleChange('email',e)}
name=“电子邮件”
/>
handleChange('password',e)}
name=“密码”
/>

创建一个包含所有输入的字典

您可以使用输入的
名称
为对象(用作字典)中的每个输入保存
状态
设置状态
的引用

下面的示例也适用于
复选框
输入:

import React, { useState } from "react";
const setStateOfInput = 1;

function Form() {
  const inputs = {}; // Dictionary used to save a reference [state, setState] for each input (e.g. inputs.todo)
  const [todoInput, setTodoInput] = inputs.todo = useState("");
  const [doneInput, setDoneInput] = inputs.done = useState(false);

  function handleInput(e) {
    let { name, value, type } = e.target;
    // If input is a checkbox
    if (type === "checkbox") value = e.target.checked;

    inputs[name][setStateOfInput](value);
  }

  return (
    <div>
      <form>
        <label>To Do</label>
        <input name="todo" value={todoInput} onChange={handleInput} />

        <label>Done</label>
        <input name="done" type="checkbox" checked={doneInput} onChange={handleInput}/>

        <button type="button">Add</button>
      </form>
    </div>
  );
}

export default Form;
|


谢谢。我完全忘了setState可以回电话。我最近没用过。但感谢上帝,这是国家的一部分。还有其他方法吗?您可以创建自定义挂钩“useMyState”。您可以返回{state,update}或[,]。您可以编写这样一个更新函数,最后在您自己的组件中,您可以说‘update({email:'newValue'})’或‘update('email','newValue'),这将适合您的句柄更改部分使用它而不是原始状态对象有什么区别吗?即,
const[state,setState]=useState({name:'',email:''})->
setState({…状态,名称:'Jane'})是。在你的例子中,你不会有同样的效果。创建一个具有数字值的测试组件。在for循环中,需要将该值增加5倍。你会看到他们有多么不同are@DoğancanArabacı在一个循环中这样做似乎是不好的做法。和我举的例子不一样。谢谢。是的,这是可行的,但找到了一个较短的解决方案。我还需要一个对象来处理:)你能发布你的解决方案供大家启发吗。检查最后一个答案:)你忘记了一个
这里:
prevState=>({
该死,我在一个组件中使用了多个useState属性,后来不得不使用这种方法折射所有内容,这样它更容易测试(模拟单个useState返回更容易、更健壮)。尽可能提前计划,伙计们,别做我。
<input
    type="text"
    onChange={ e => handleChange('email',e)}
    name="email"
  />
<input
    type="text"
    onChange={ e => handleChange('password',e)}
    name="password"
  />
import React, { useState } from "react";
const setStateOfInput = 1;

function Form() {
  const inputs = {}; // Dictionary used to save a reference [state, setState] for each input (e.g. inputs.todo)
  const [todoInput, setTodoInput] = inputs.todo = useState("");
  const [doneInput, setDoneInput] = inputs.done = useState(false);

  function handleInput(e) {
    let { name, value, type } = e.target;
    // If input is a checkbox
    if (type === "checkbox") value = e.target.checked;

    inputs[name][setStateOfInput](value);
  }

  return (
    <div>
      <form>
        <label>To Do</label>
        <input name="todo" value={todoInput} onChange={handleInput} />

        <label>Done</label>
        <input name="done" type="checkbox" checked={doneInput} onChange={handleInput}/>

        <button type="button">Add</button>
      </form>
    </div>
  );
}

export default Form;
function useInputState(initialValue, name, inputsDict) {
  if (inputsDict[name]) throw new Error(`input "${name}" already exists.`);

  inputsDict[name] = useState(initialValue);
  return inputsDict[name]
}
const inputs = {}; // Dictionary used by `useInputState`
const [todoInput, setTodoInput] = useInputState("", "todo", inputs);