Почему значение отклоняется из поля ввода в React, когда useState используется не для значения, а для объекта?

#javascript #reactjs #typescript

Вопрос:

У меня здесь есть текстовое поле:

 <TextFieldItem
  primary="Barion ID"
  required="**"
  value={selectedOrganization?.barionId ?? ""}
  onChange={(event: React.ChangeEvent<HTMLInputElement>) => {
    selectedOrganization.barionId = event.target.value;
    setSelectedOrganization(selectedOrganization);
  }}
  onBlur={() => validateBarionId()}
  disabled={
    !selectedOrganizationId || !userFbId || editBarionIdIsDisabled
  }
  placeholder="e-mail"
  helperText={barionIdHelperText}
/>
 

Здесь у меня есть переменная состояния:

 const [selectedOrganization, setSelectedOrganization] = useState<
  OrganizationOut | undefined
>(undefined);
 
 export type OrganizationOut = {
  name?: string;
  barionId?: string;
 

И он сохраняет пустую строку, неважно, что я там пишу, она всегда пуста.

Когда раньше отображалась атомарная строка, она работала, но теперь, когда она завернута в объект, это не так. Ты знаешь, почему?


1 получил эту ошибку при использовании ОТВЕТА 1

 ./pages/[lang]/onboarding2.tsx:645:51
Type error: Argument of type '(preState: OrganizationOut | undefined) => { szamlazzhuSzamlaAgentKulcsTemp: string; name?: string | undefined; barionId?: string | undefined; barionIdTemp?: string | undefined; ... 18 more ...; urlPrefix?: string | undefined; }' is not assignable to parameter of type 'SetStateAction<OrganizationOut | undefined>'.
  Type '(preState: OrganizationOut | undefined) => { szamlazzhuSzamlaAgentKulcsTemp: string; name?: string | undefined; barionId?: string | undefined; barionIdTemp?: string | undefined; ... 18 more ...; urlPrefix?: string | undefined; }' is not assignable to type '(prevState: OrganizationOut | undefined) => OrganizationOut | undefined'.
    Call signature return types '{ szamlazzhuSzamlaAgentKulcsTemp: string; name?: string | undefined; barionId?: string | undefined; barionIdTemp?: string | undefined; szamlazzhuSzamlaAgentKulcs?: string | undefined; ... 17 more ...; urlPrefix?: string | undefined; }' and 'OrganizationOut | undefined' are incompatible.
      The types of 'events' are incompatible between these types.
        Type '{ [eventId: string]: EventOut; } | undefined' is not assignable to type '{ [eventId: string]: EventOut; }'.
          Type 'undefined' is not assignable to type '{ [eventId: string]: EventOut; }'.

  643 |                           selectedOrganization.szamlazzhuSzamlaAgentKulcsTemp =
  644 |                             event.target.value;
> 645 |                           setSelectedOrganization((preState) => ({
      |                                                   ^
  646 |                             ...preState,
  647 |                             szamlazzhuSzamlaAgentKulcsTemp: event.target.value!,
  648 |                           }));
error Command failed with exit code 1.
 

Ответ №1:

Потому что вы неправильно настроили объект состояния.

 setSelectedOrganization(preState => ({ ...preState, barionId: event.target.value }));
 

Вы можете прочитать подробную информацию в документах:

состояние — это ссылка на состояние компонента в момент применения изменения. Он не должен подвергаться прямой мутации. Вместо этого изменения должны быть представлены созданием нового объекта на основе входных данных из состояния и реквизитов.

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

1. Спасибо, уоркс, не могли бы вы объяснить, почему, в чем разница?

2. Я добавил документ

3. спасибо, не могли бы вы помочь еще немного? Знаете ли вы, почему я получил сообщение об ошибке, прикрепленное к вопросу, когда я запускаю yarn build ?

Ответ №2:

Никогда не изменяйте фактическое состояние. Состояние должно использоваться как значение только для чтения, которое представляет значение состояния, поддерживаемое React. Однако любые изменения в нем не изменяют фактическое состояние. Вот setState для чего это нужно.

Во-вторых, React использует === сравнение, чтобы проверить, было ли изменено состояние. Когда вы передаете массив или объект setState функции, она сравнивает их по ссылке, а не по значению. Это означает, что вам нужно создать новый объект или массив, а не использовать один и тот же:

 const [state, setState] = useState({});

state.a = 5; // Mistake: never modify the actual state!
setState(state); // Mistake: setState will not update because reference is the same
 

Вместо этого вам нужно создать новый объект (или массив) из текущего состояния, изменить его, а затем, наконец, использовать его для setState :

 const [state, setState] = useState({});

const newState = {...state}; // Create a shallow copy of the state
newState.a = 5; // Modify the copy, and not the real state
setState(newState); // Set the state to the copy, that has a different reference