Заполнение и сохранение данных. Best practices

Друзья, добрый день!

Вроде стандартная задача. Заполнить данные формы-анкеты пользователя и сохранить в БД. Форма анкеты - набор компонентов, такие как: Основная информация, Паспорные данные, Хобби и увлечения и т.п. + кнопка Сохранить.

Сейчас я сделал как. Есть класс описывающий анкету (модель). При создании компонента создаю экземпляр этого класса в useRef. Далее, во все дочерние компоненты передаю эту переменную через св-ва. В компонентах заполняются соответствующие св-ва переменной. Таким образом при нажатии на кнопку Сохранить я имею доступ к заполненной модели. Здесь смоделировал ситуацию на примере: https://stackblitz.com/edit/react-ts-4fpzky

Скажите, нормальный такой поход для заполнения данных сложного объекта? Может быть лучше сделать по другому? Есть ли какой-либо best practices? Или может стоить меппить поля объекта сразу на контролы, без дополнительных переменных состояния? Но тогда ведь при каждом измененении будет перересовываться вся форма. Стоит ли задействовать redux для таких задач?

model.ts

class Model {
  // Component 1
  firstName: string;
  lastName: string;

  // Component 2
  passport: string;
  address: string;
}

interface IComponent {
  model: Model;
}

export { Model, IComponent };

index.tsx

export const App: React.FunctionComponent<{}> = () =>
{
 const model = useRef<Model>(new Model());

 const save = () =>{
   console.log(model.current);
 }

return (
  <React.Fragment>
    <Component1 model={model.current} />
    <Component2 model={model.current} />
    <button onClick={save}>Сохранить</button>
  </React.Fragment>
);
}
render(<App />, document.getElementById('root'));

Component1.tsx

export const Component1: React.FunctionComponent<IComponent> = ({ model }) => {

  const [firstNameValue, setFirstNameValue] = useState(model.firstName);
  const [lastNameValue, setLastNameValue] = useState(model.lastName);

  const changeFirstName = (e: React.ChangeEvent<HTMLInputElement>) => {
      model.firstName = e.target.value;
      setFirstNameValue(e.target.value);
  }

  const changeLastName = (e: React.ChangeEvent<HTMLInputElement>) => {
      model.lastName = e.target.value;
      setLastNameValue(e.target.value);
  }

  return (
  <React.Fragment>
   <div>
    <label htmlFor="firstName">FirstName:</label>
    <input name="firstName" value={firstNameValue} onChange={changeFirstName} />
   </div>
   <div>
    <label htmlFor="lastName">LastName:</label>
    <input name="lastName" value={lastNameValue} onChange={changeLastName}/>
   </div>
  </React.Fragment>);
};

Component2.tsx

export const Component2: React.FunctionComponent<IComponent> = ({ model }) => {
   const [passportValue, setPassportValue] = useState(model.passport);
   const [addressValue, setAddressValue] = useState(model.address);

  const changePassport = (e: React.ChangeEvent<HTMLInputElement>) => {
      model.passport = e.target.value;
      setPassportValue(e.target.value);
  }

  const changeAddress = (e: React.ChangeEvent<HTMLInputElement>) => {
      model.address = e.target.value;
      setAddressValue(e.target.value);
  }

  return (
  <React.Fragment>
   <div>
    <label htmlFor="passport">Паспорт:</label>
    <input name="passport" value={passportValue} onChange={changePassport} />
   </div>
   <div>
    <label htmlFor="address">Адрес:</label>
    <input name="address" value={addressValue} onChange={changeAddress}/>
   </div>
  </React.Fragment>);
};

Ответы (0 шт):