3
votes

Réagir le hook d'état avec un objet

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>
  );
};
I am working with react hooks. I set the initial state to an object. I try changing the value with react hooks but this gives an error TypeError: setUser.name is not a function

1 commentaires

setUser est une fonction et non un objet, c'est ce que vous essayez de faire. il suffit de le changer en setUser ((prevState) => {... prevState, name: e.target.value)} />


3 Réponses :


8
votes

setUser est une fonction que vous utilisez pour mettre à jour l'état et comme il remplace simplement l'état dont vous avez besoin pour fusionner également votre valeur d'état précédente. L'événement est également effacé dans le rappel, vous devez donc obtenir la valeur avant d'utiliser le rappel de setUser. Il est préférable d'écrire une fonction de gestionnaire pour cela. Vous pouvez également écrire une fonction générique pour gérer la définition de toutes les valeurs

<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" />
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'));


2 commentaires

Obtention de cette erreur: TypeError: impossible de lire la propriété 'value' de null


@Navish Avez-vous créé le gestionnaire comme je l'ai suggéré, vous devez lire la valeur avant le rappel du programme de mise à jour de l'état, sinon il sera effacé



2
votes

setUser est une fonction identique à setState .. pour plus de détails, consultez hooks

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

dans votre contexte:

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


0 commentaires

3
votes

Regardons la valeur de User et setUser

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

React.useState renvoie une valeur et un setter à cette valeur. setUser est une fonction. Ainsi, alors que User.name est une chaîne avec la valeur initiale "ed", setUser.name n'existe pas. L'erreur TypeError: setUser.name n'est pas une fonction est le résultat d'une tentative de passer une valeur indéfinie en argument. Une façon de résoudre ce problème est comme le suggèrent Murtaza Hussain et d'autres réponses:

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

Comme alternative, vous pouvez utiliser un hook useObjState personnalisé, qui fournit un API assez simple.

Hook UseObjState

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

Il fournit un moyen beaucoup plus simple / plus propre de mettre à jour la valeur de la propriété name.

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

Démo p>


2 commentaires

Salut Ben, cela ne répond pas à la question initiale, cela suggère une alternative. Je mettrais cela comme un commentaire et non comme une réponse, car quelqu'un pourrait marquer ou voter contre. Juste mon avis. C'est une excellente suggestion, mais pas une réponse à la question de savoir pourquoi il obtient une erreur sur le code qu'il a écrit spécifiquement.


@EricBishard, merci pour votre commentaire. Je suis d'accord. J'ai fait quelques ajustements pour mieux répondre à la question. Jetez un œil et faites-moi savoir si vous pensez toujours qu'il y a un problème.