#where should i update the setSelectedItem state to get the value when its being typed in the input

15 messages · Page 1 of 1 (latest)

noble depot
#
export default function Menu() {
  const [items, setItems] = useState(initialItems);
  const [selectedItem, setSelectedItem] = useState(
    items[0]
  );

  function handleItemChange(id, e) {
    setItems(items.map(item => {
      if (item.id === id) {
        setSelectedItem(item);
        return {
          ...item,
          title: e.target.value,
        };
      }
      else {
        return item;
      }
    }
    )
    );
  }

  return (
    <>
      <h2>What's your travel snack?</h2> 
      <ul>
        {items.map((item, index) => (
          <li key={item.id}>
            <input
              value={item.title}
              onChange={e => {
                handleItemChange(item.id, e)
              }}
            />
            {' '}
            <button onClick={() => {
              setSelectedItem(item);
            }}>Choose</button>
          </li>
        ))}
      </ul>
      <p>You picked {selectedItem.title}.</p>
    </>
  );
}

where should i update the setSelectedItem show that the selectedItem.title updates in real time

kindred plover
#

Hi @noble depot - you're going to want to handle everything in the handleItemChange function. What you're going for is a controlled component. FIrst off, you would need to add a name property to your text input. Then you will want to update your handleItemChange function, it's not exactly correct.

kindred plover
#
  function handleItemChange(id, e) {
      setItems(items.map(item -> {
        if (item.id === id) {
          setSelectedItem(prevState => {
      ...prevState,
      [e.target.name]: e.target.value
          }))
        }
        return item
      }
    }
#

Something like this

#

You need to a name to get access to e.target.name so you'd do add <input name="title" in this case along with the other properties so it's like <input type="text" onChange={handleItemChange(item.id)} name="title" />

#

You can update any field with the same changehandler that way if you add a name to each input, it will target the correct property in the item object corresponding to the name.

noble depot
#

okay

#

but

#

now i can only add one letter and it wont let me add more letters

kindred plover
#

do you have code on github at all? maybe I can try messing with it It is difficult to tell what is going on from here. But that is the right direction to go in, before it was not registering any input?

noble depot
#
function handleItemChange(id, e) {
    setItems(
      items.map((item) => {
        if (item.id === id) {
          setSelectedItem((prevState) => {
            return {
              ...prevState,
              [e.target.name]: e.target.value
            };
          });
          return {
            ...item,
            [e.target.name]: e.target.value
          };
        } else {
          return item;
        }
      })
    );
  }
#

this is working but is it the right way?

noble depot
kindred plover
#

it may be helpful to split the form out into its own component that holds its own state and then have the submit bubble back up to the outer component, you can pass the function to update the selected item as a prop