React - 使用嵌套对象作为带有钩子的状态来填充表单数据

问题描述

我有一个嵌套对象,如下所示 -

const [userInfo,setUserInfo] = useState({
    author:"",user: {
      name: 'rahul',email: 'rahul@gmail.com',phone: [{ primary: '8888888810' },{ alternate: '7777777716' }]
    }
  });

我想要 5 个输入字段 - 作者、姓名、电子邮件、主要和备用,并且只想使用一个 handleChange() 方法来更改字段

你可以在链接上找到我写的代码 - https://stackblitz.com/edit/react-ngpx7q

在这里,我无法弄清楚如何正确更新状态。任何帮助将不胜感激。

解决方法

由于这是一个面试问题,所以我会避免使用 3rd 方库。您可以使用 switch 语句来处理不同的嵌套状态,即第二级的 nameemail 以及第三级的 primaryalternate .

const handleChange = (e) => {
  const { name,value } = e.target;

  switch (name) {
    case "name":
    case "email":
      setUserInfo((userInfo) => ({
        user: {
          ...userInfo.user,[name]: value
        }
      }));
      break;

    case "primary":
    case "alternate":
      setUserInfo((userInfo) => ({
        user: {
          ...userInfo.user,phone: userInfo.user.phone.map((el) =>
            el.hasOwnProperty(name)
              ? {
                  [name]: value
                }
              : el
          )
        }
      }));
      break;

    default:
    // ignore
  }
};

演示

Edit react-handling-nested-objects-as-state-using-hooks

,

您可以使用 lodash set 为深度嵌套的对象分配值。您需要将 path 传递给输入的 name 道具。

import set from 'lodash/set'

const App = () => {
  const [userInfo,setUserInfo] = useState({
    author:"",user: {
      name: 'rahul',email: 'rahul@gmail.com',phone: [{ primary: '8888888810' },{ alternate: '7777777716' }]
    }
  });

  const handleChange = (e) => {
    // clone the state
    const userInfoCopy = JSON.parse(JSON.stringify(userInfo));
    set(userInfoCopy,e.target.name,e.target.value)
    setUserInfo(userInfoCopy)
  }

  console.log(userInfo)

  return (
    <div>
      <input
        name="user.name"
        onChange={handleChange}
      />
       <input
        name="user.phone.[0].primary"
        onChange={handleChange}
      />     
    </div>
  );
};

现在您可以使用单个 handleChange 方法更新状态中的所有密钥。

,

我认为这不是一个好主意,而不是将手机视为数组对象,而是将其视为单个对象,主要和备用作为键值对

import React,{ useState } from 'react';
import './style.css';

export default function App() {
  const [userInfo,setUserInfo] = useState({
    user: {
      name: 'ravi',email: 'ravi@gmail.com',phone: {
        primary: 345345345345,alternate: 234234234234
      }
    }
  });

  const handleChange = e => {
    console.log(e.target.name);
    setUserInfo(prevState => {
      return {
        user: {
          ...prevState.user,[e.target.name]: e.target.value,phone: {
            ...prevState.user.phone,...{ [e.target.name]: e.target.value }
          }
        }
      };
    });
  };

  const {
    name,email,phone: { primary,alternate }
  } = userInfo.user;

  console.log(userInfo);

  return (
    <div className="App">
      Name: <input name="name" value={name} onChange={e => handleChange(e)} />
      <br />
      Email:{' '}
      <input name="email" value={email} onChange={e => handleChange(e)} />
      <br />
      Primary:{' '}
      <input name="primary" value={primary} onChange={e => handleChange(e)} />
      <br />
      Alternate:{' '}
      <input
        name="alternate"
        value={alternate}
        onChange={e => handleChange(e)}
      />
      <br />
    </div>
  );
}
,

这基于您的原始数据(其中 phone 是一组对象):

const handleChange = e => {
    let name = e.target.name;
    if (['name','email'].includes(name)) {
      setUserInfo(prevState => {
        return {
          user: {
            ...prevState.user,[name]: e.target.value,}
        };
      });
    } else {
      setUserInfo(prevState => {
        return {
          user: {
            ...prevState.user,phone: name === 'primary' ?
             [prevState.user.phone.find(e => Object.keys(e).includes('alternate')),{[name]: e.target.value}] :
             [prevState.user.phone.find(e => Object.keys(e).includes('primary')),{[name]: e.target.value}]
          }
        };
      });
    }
  };
,

我复制粘贴你的代码,只编辑你的 handleChange

import React,phone: [{ primary: '9999999990' },{ alternate: '9999998880' }]
    }
  });



  const handleChange = e => {
    console.log(e.target.name);
    let arrPhone = userInfo.user.phone;
    (e.target.name == 'primary' || e.target.name == 'alternate' ) 
    && arrPhone.map(x => (x.hasOwnProperty(e.target.name)) && (x[e.target.name] = e.target.value))

    console.log(arrPhone)
    setUserInfo(prevState => {
      return {
        user: {
          ...prevState.user,phone: arrPhone
        }
      };
    });
  };

  const {
    name,phone: [{ primary },{ alternate }]
  } = userInfo.user;

  console.log(userInfo);

  return (
    <div className="App">
      Name: <input name="name" value={name} onChange={handleChange} />
      <br />
      Email: <input name="email" value={email} onChange={handleChange} />
      <br />
      Primary: <input name="primary" value={primary} onChange={handleChange} />
      <br />
      Alternate:{' '}
      <input name="alternate" value={alternate} onChange={handleChange} />
      <br />
    </div>
  );
}