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>
  );
};

Estoy trabajando con ganchos de reacción. Configuré el estado inicial de un objeto. Intento cambiar el valor con ganchos de reacción pero esto produce un error TypeError: setUser.name is not a function

2
Navish 10 may. 2019 a las 13:56

3 respuestas

La mejor respuesta

Veamos el valor de Usuario y setUser

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

React.useState devuelve un valor y un setter a ese valor. setUser es una función. Entonces, mientras que User.name es una cadena con el valor inicial de "ed" setUser.name no existe. El error TypeError: setUser.name is not a function es el resultado de intentar pasar un valor indefinido a un argumento. Una forma de resolver esto es como sugieren Murtaza Hussain y otras respuestas:

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

Como alternativa, puede usar un gancho personalizado useObjState, que proporciona una API bastante simple.

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];
};

Proporciona una manera mucho más fácil / limpia de actualizar el valor de la propiedad de nombre.

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)} />
    />
  )
}

Demo

3
Ben Carp 22 jun. 2019 a las 18:20

setUser es una función que utiliza para actualizar el estado y, dado que simplemente reemplaza el estado, también necesita fusionar su valor de estado anterior. Además, el evento se borra en la devolución de llamada, por lo que debe obtener el valor antes de usar la devolución de llamada de setUser. Es mejor escribir una función de controlador para esto. También puede escribir una función genérica para manejar la configuración de todos los valores

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" />
8
Shubham Khatri 10 may. 2019 a las 11:17

setUser es una función igual que setState .. para obtener más información, consulte ganchos

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

En tu contexto:

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}))}
      />
  );
};
1
Murtaza Hussain 10 may. 2019 a las 11:12