Двусторонняя привязка prop-объекта в форме реакции функционального компонента

#javascript #reactjs

#javascript #reactjs

Вопрос:

Итак, я работаю над модальной формой для изменения объекта (т. Е. Продавца). Я могу либо отправить пустой объект в свой реквизит, чтобы добавить продавца, либо передать существующий объект продавца для их редактирования.

Я могу привязать значения к своим элементам управления, но я не уверен, как заставить 2-стороннюю привязку работать с любыми изменениями значения. Я предполагаю, что это будет какой-то onChange синтаксис, возможно, с локальным useState объектом для хранения изменений, но не уверен, как это будет выглядеть.

Рад предоставить более подробную информацию или контекст, если это необходимо.

 import React from 'react';
import Modal from '../components/Modal'


function ModifySalespersons(props) {

  function submit(salesperson) {
    console.log(salesperson);
    // return new salesperson object
    props.setIsOpen(false);
  }

  return (
    <Modal isOpen={props.isOpen} setIsOpen={props.setIsOpen} content={
      <>
        <div>
          <div>
            <h3 class="text-lg leading-6 font-medium text-gray-900">
              Salesperson Information
            </h3>
          </div>

          <form class="mt-6 sm:mt-5">
            <div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
              <label for="first_name" class="block text-sm font-medium leading-5 text-gray-700 sm:mt-px sm:pt-2">
                First name
              </label>
              <div class="mt-1 sm:mt-0 sm:col-span-2">
                <div class="max-w-lg rounded-md shadow-sm sm:max-w-xs">
                  <input value={props.salesperson.firstName} id="first_name" class="form-input block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5" />
                </div>
              </div>
            </div>

            <div class="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start">
              <label for="last_name" class="block text-sm font-medium leading-5 text-gray-700 sm:mt-px sm:pt-2">
                Last name
              </label>
              <div class="mt-1 sm:mt-0 sm:col-span-2">
                <div class="max-w-lg rounded-md shadow-sm sm:max-w-xs">
                  <input value={props.salesperson.lastName} id="last_name" class="form-input block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5" />
                </div>
              </div>
            </div>

            <div class="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
              <label for="address1" class="block text-sm font-medium leading-5 text-gray-700 sm:mt-px sm:pt-2">
                Address
              </label>
              <div class="mt-1 sm:mt-0 sm:col-span-2">
                <div class="max-w-lg rounded-md shadow-sm sm:max-w-xs">
                  <input value={props.salesperson.address1} id="address1" class="form-input block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5" />
                </div>
              </div>
            </div>

{/* more controls here */}

          </form>
        </div>

        <div class="mt-5 sm:mt-6 space-y-2">
          <span class="flex w-full rounded-md shadow-sm">
            <button onClick={() => submit(props.salesperson)} type="button" class="inline-flex justify-center w-full rounded-md border border-transparent px-4 py-2 bg-indigo-600 text-base leading-6 font-medium text-white shadow-sm hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:shadow-outline-indigo transition ease-in-out duration-150 sm:text-sm sm:leading-5">
              Submit
            </button>
          </span>

          <span class="flex w-full rounded-md shadow-sm">
            <button onClick={() => props.setIsOpen(false)} type="button" class="inline-flex justify-center w-full rounded-md border border-transparent px-4 py-2 bg-white text-base leading-6 font-medium text-gray-500 shadow-sm hover:bg-gray-100 focus:outline-none focus:border-gray-700 focus:shadow-outline-gray transition ease-in-out duration-150 sm:text-sm sm:leading-5">
              Cancel
            </button>
          </span>
        </div>
      </>
    } />
  );
}

export default ModifySalespersons;
  

Комментарии:

1. Вы можете использовать const [salesperson, setSalesperson] = useState(props.salesperson || {}) и в JSX salesperson.. вместо props.salesperson.. и, как вы сказали, добавить onChange слушателей к входным данным и изменить состояние.

Ответ №1:

ШАГИ

  1. Инициализируйте свое состояние с помощью реквизита из родительского элемента, который переносится Salesperson .
  2. Свяжите свое состояние с полями ввода, используя value from state и onChange .
  3. Передайте вашей функции Salesperson , которая принимает вашего нового отредактированного продавца.
  4. После отправки формы вызовите свою функцию, переданную от дочернего элемента, и выполните следующий шаг.

Вы можете проверить рабочий пример здесь -> https://stackblitz.com/edit/react-jghg5q

 import React from "react";
import Modal from "../components/Modal";

export default function ComponentThatWrapsModifySalespersons() {
  function handleSubmit(newSalesperson) {
    console.log(newSalesperson);
  }

  return (
    <ModifySalespersons
      salesperson={{ firstName: "hello", lastName: "world", address: "calif" }}
      onSubmit={handleSubmit}
    />
  );
}

function ModifySalespersons(props) {
  const [state, setState] = React.useState({ ...props.salesperson });

  function handleChange(e) {
    const key = e.target.name;
    const value = e.target.value;

    setState(prev => ({
      ...prev,
      [key]: value
    }));
  }

  function submit() {
    // return new salesperson object
    props.onSubmit(state);
    // props.setIsOpen(false);
  }

  console.log(state);

  return (
    <>
      <div>
        <div>
          <h3 class="text-lg leading-6 font-medium text-gray-900">
            Salesperson Information
          </h3>
        </div>

        <form class="mt-6 sm:mt-5">
          <div class="sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
            <label
              for="first_name"
              class="block text-sm font-medium leading-5 text-gray-700 sm:mt-px sm:pt-2"
            >
              First name
            </label>
            <div class="mt-1 sm:mt-0 sm:col-span-2">
              <div class="max-w-lg rounded-md shadow-sm sm:max-w-xs">
                <input
                  name="firstName"
                  onChange={handleChange}
                  value={state.firstName}
                  id="first_name"
                  class="form-input block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5"
                />
              </div>
            </div>
          </div>

          <div class="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start">
            <label
              for="last_name"
              class="block text-sm font-medium leading-5 text-gray-700 sm:mt-px sm:pt-2"
            >
              Last name
            </label>
            <div class="mt-1 sm:mt-0 sm:col-span-2">
              <div class="max-w-lg rounded-md shadow-sm sm:max-w-xs">
                <input
                  name="lastName"
                  onChange={handleChange}
                  value={state.lastName}
                  id="last_name"
                  class="form-input block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5"
                />
              </div>
            </div>
          </div>

          <div class="mt-6 sm:mt-5 sm:grid sm:grid-cols-3 sm:gap-4 sm:items-start sm:border-t sm:border-gray-200 sm:pt-5">
            <label
              for="address1"
              class="block text-sm font-medium leading-5 text-gray-700 sm:mt-px sm:pt-2"
            >
              Address
            </label>
            <div class="mt-1 sm:mt-0 sm:col-span-2">
              <div class="max-w-lg rounded-md shadow-sm sm:max-w-xs">
                <input
                  name="address"
                  onChange={handleChange}
                  value={state.address}
                  id="address1"
                  class="form-input block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5"
                />
              </div>
            </div>
          </div>

          {/* more controls here */}
        </form>
      </div>

      <div class="mt-5 sm:mt-6 space-y-2">
        <span class="flex w-full rounded-md shadow-sm">
          <button
            onClick={submit}
            type="button"
            class="inline-flex justify-center w-full rounded-md border border-transparent px-4 py-2 bg-indigo-600 text-base leading-6 font-medium text-white shadow-sm hover:bg-indigo-500 focus:outline-none focus:border-indigo-700 focus:shadow-outline-indigo transition ease-in-out duration-150 sm:text-sm sm:leading-5"
          >
            Submit
          </button>
        </span>

        <span class="flex w-full rounded-md shadow-sm">
          <button
            onClick={() => props.setIsOpen(false)}
            type="button"
            class="inline-flex justify-center w-full rounded-md border border-transparent px-4 py-2 bg-white text-base leading-6 font-medium text-gray-500 shadow-sm hover:bg-gray-100 focus:outline-none focus:border-gray-700 focus:shadow-outline-gray transition ease-in-out duration-150 sm:text-sm sm:leading-5"
          >
            Cancel
          </button>
        </span>
      </div>
    </>
  );
}


  

Комментарии:

1. Спасибо! Вот-вот закончится, и я смотрю на это на мобильном устройстве, но, кажется, я понимаю, к чему вы клоните. Сегодня вечером я снова посмотрю на это.

2. Хорошо, круто. Кажется, я понял. Мне потребовалась минута, но мне не хватало name атрибута, который позволил бы мне обновить поле. Оцените это!

Ответ №2:

для этой цели вы можете использовать useEffect . он будет искать изменения в вашем props.salesperson и действовать соответствующим образом

 const [isForEdit , setIsForEdit] = useState(false);

useEffect( () => {
  setIsForEdit(). /// -> true or false based on the value of props.salesperson 
}, [props.salesperson]) 

  

теперь, основываясь на значении isForEdit, вы можете решить делать все, что захотите.