0

I'm trying to update a single key/value pair in a user object which contains another array of object called "education". I set a custom attribute called "index" on the list components to access the array index when updating.

// User object
const [userData, setUserData]  = useState({
    firstName: '',
    lastName: '',
    title: '',
    email: '',
    phoneNumber: '',
    website: '',
    bio: '',
    education: [
      {
        id: uniqid(),
        school: '',
        degree: '',
        city: '',
        state: '',
        timeframe: ''

      }
    ]
})
// Render input form for Education
const listItems = props.userData.education.map((user, index) => {
    return (
      <div key={index}>
        <h2>University/School #{index}</h2>
        <input
          type="text"
          index={index}
          placeholder="Your school"
          name="school"
          onChange={props.handleChange}
          value={props.userData.education[index].school}
        />
      </div>
    );
  });

Created this fucntion handler for onChange but it just returns an empty string and doesn't update the object. I feel i'm using the spread operator here wrongly but can't figure out how to put all together rightly.

// Update user education state
const handleChange = (e) => {
  const { value, name } = e.target
  const index = e.target.getAttribute('index')
  setUserData(prevUser => ({
    ...prevUser,
    [prevUser.education[index]]: {
      [name]: value
    }
  }))
}

1 Answer 1

1

You don't need to add a custom index value and get it off an attribute. You can add it to your change callback:

const listItems = props.userData.education.map((user, index) => {
    return (
      <div key={index}>
        <h2>University/School #{index}</h2>
        <input
          type="text"
          index={index}
          placeholder="Your school"
          name="school"
          onChange={(e) => props.handleChange(e, index)}
          value={props.userData.education[index].school}
        />
      </div>
    );
  });

if you run console.log inside your handleChange what do you see for value and name?

I am hoping you can learn a bit about how to debug your code.

const handleChange = (e, index) => {

  const { value, name } = e.target
  console.log({value});
  console.log({name});

  setUserData(prevUser => {
    const newItem = {
       [prevUser.education[index]]: {
          [name]: value
       }
    }
    console.log({newItem}); // is this what you expect?

    return ({
    ...prevUser,
    ...newItem,
    
  })))
}

Finally, your value should come from state directly, not Props. I am assuming your state is inside the same component as your rendering? Otherwise, are you passing state as a prop to your consuming component?

As for your spread, yes, you are missing a little.

const newItem = {
       [prevUser.education[index]]: {
         ...[prevUser.education[index]], // without this you will overwrite all the previous data
          [name]: value
       }
    }
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.