簡體   English   中英

React - 使用嵌套對象作為 state 並帶有鈎子來填充表單數據

[英]React - using nested objects as state with hooks to fill form data

我有一個嵌套的 object 作為 state 如下所示 -

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

我想要 5 個輸入字段 - 作者、姓名、email、主要和備用字段,並且只想使用一個 handleChange() 方法來更改字段

您可以在鏈接上找到我寫的代碼 - https://stackblitz.com/edit/react-ngpx7q

在這里,我無法弄清楚如何正確更新 state。 任何幫助將不勝感激。

由於這是一個面試問題,所以我會避免使用 3rd-party 庫。 您可以使用switch語句來處理不同嵌套的state,即第二層的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
  }
};

演示

編輯 react-handling-nested-objects-as-state-using-hooks

您可以使用 lodash set為深度嵌套的 object 分配值。 您需要將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方法來更新 state 中的所有密鑰。

與其將電話視為數組的 object(我認為這不是一個好主意),不如將其視為單個 object,將主要和備用作為鍵值對

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, { useState } from 'react';
import './style.css';

export default function App() {
  const [userInfo, setUserInfo] = useState({
    user: {
      name: 'ravi',
      email: 'ravi@gmail.com',
      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,
          [e.target.name]: e.target.value,
          phone: arrPhone
        }
      };
    });
  };

  const {
    name,
    email,
    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>
  );
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM