Реагировать на состояние с помощью объекта - PullRequest
1 голос
/ 10 мая 2019
const App = () => {
  const [User, setUser] = useState({
    id: 1,
    name: "ed",
    age: Number,
    edit: false
  });
  return (
    <div>
      <input value={User.name} onChange={e => setUser.name(e.target.value)} />
    </div>
  );
};

Я работаю с реактивными крючками.Я установил начальное состояние для объекта.Я пытаюсь изменить значение с помощью перехватчиков, но это выдает ошибку TypeError: setUser.name is not a function

Ответы [ 3 ]

6 голосов
/ 10 мая 2019

setUser - это функция, которую вы используете для обновления состояния, и, поскольку она просто заменяет состояние, вам также необходимо объединить предыдущее значение состояния.Также событие очищается в обратном вызове, поэтому вам нужно получить значение перед использованием обратного вызова setUser.Для этого лучше написать функцию-обработчик.Также вы можете написать универсальную функцию для обработки установки всех значений

const App = () => {
      const [User, setUser] = React.useState({
        id: 1,
        name: "ed",
        age: Number,
        edit: false
      }); 
      const handleChange = (e) => {
         const {value, name} = e.target;
         setUser(prev => ({...prev, [name]: val}))
      }
      return (
        <div>
          <input value={User.name} onChange={handleChange} />
        </div>
      );
    };
    ReactDOM.render(<App />, document.getElementById('app'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="app" />
2 голосов
/ 22 июня 2019

Давайте посмотрим на значение User и setUser

const [User, setUser] = useState({
    id: 1,
    name: "ed",
    age: Number,
    edit: false
  });

React.useState возвращает значение и установщик этого значения. setUser - это функция. Поэтому, хотя User.name является строкой с начальным значением "ed", setUser.name не существует. Ошибка TypeError: setUser.name is not a function является результатом попытки передать неопределенное значение аргументу. Один из способов решения этой проблемы - Муртаза Хуссейн и другие ответы:

  <input 
    value={User.name}
    onChange={e => setUser(prev => ({...prev, name: e.target.value}))}
  />

В качестве альтернативы вы можете использовать пользовательский хук useObjState, который предоставляет довольно простой API.

UseObjState hook

const useObjState = initialObj => {
  const [obj, setObj] = React.useState(initialObj);
  const setObjHelper = useMemo( () => { // the value of setObjHelper is permanent, so even if it is passed to a child component, it shouldn't require extra component updates
    const helper = {}
    Object.keys(initialObj).forEach(key => {
      helper[key] = newVal => setObj({ ...obj, [key]: newVal });
    });
    return helper
  }, [])
  return [obj, setObjHelper];
};

Предоставляет гораздо более простой и понятный способ обновления значения свойства name.

function App() {
  const [user, setUser] = useObjState({
    id: 1,
    name: "ed",
    age: Number,
    edit: false
  });

  return (
    <input 
      value={user.name} 
      onChange={e => setUser.name(e.target.value)} />
    />
  )
}

Демо

1 голос
/ 10 мая 2019

setUser является функцией, аналогичной setState .. для более подробной информации проверьте hooks

  <input 
    value={User.name}
    onChange={e => setUser(prev => ({...prev, name: e.target.value}))}
  />

в вашем контексте:

const App = () => {
  const [User, setUser] = useState({
    id: 1,
    name: "ed",
    age: Number,
    edit: false
  });
  return (
    <div>
      <input 
        value={User.name}
        onChange={e => setUser(prev => ({...prev, name: e.target.value}))}
      />
  );
};
...