Home > OS >  My functions don't follow the synchronous using React
My functions don't follow the synchronous using React

Time:11-20

I don't know why the handleSum function doesn't sum the updated value came from handleInput when I invoke the function handleAll through the onChange input event. It seems that sums with the previous value. Can you bring some light here? Thank you!

Here the JS part:

const card = () => {

//hook defined
const [input, setInput] = React.useState({
    p1h1: "",
    p1h2: "",
});
const [result, setResult] = React.useState("")

//handle input change  
const handleInput = function(e){
    setInput({
        ...input, 
        [e.target.name]: e.target.value
    });
};

//handle sum
const handleSum = function(){
    const { p1h1, p1h2 } = input;            
    setResult(Number(p1h1)   Number(p1h2));
}

   //handle result player
   const handleAll = function (e) {
        handleInput(e)
        setTimeout (()=> {handleSum()},1000) // I inserted this setTimeout to double sure that this is executing after the previous function but didn't work.
    }
}

Here the HTML part:

<input 
  name= "p1h1" 
  value={input.p1h1} 
  onChange={handleAll} 
  type= "number" 
  min="0" 
</input>

<input 
  name= "p1h2" 
  value={input.p1h2} 
  onChange={handleAll} 
  type= "number" 
  min="0" 
</input>

<h2>Result sum: {result}</h2>

CodePudding user response:

According to the Rules of Hooks (see my comment) you may not use hooks except at the toplevel of functional components. Not nested in other functions, not in if not in for, etc.

So you need to make a functional component, like const Test = () => { return (<div />); }

Then you need to call your hook, and render your HTML as JSX from within that component. You can then use your handleInput function to update the state.

You do not need another state to hold the result of the addition. It's OK to just compute that during render.

This will work:

const Test = () => {
  //hook defined
  const [input, setInput] = React.useState({
    p1h1: '',
    p1h2: '',
  });

  //handle input change
  const handleInput = function (e) {
    setInput({
      ...input,
      [e.target.name]: e.target.value,
    });
  };
  const { p1h1, p1h2 } = input;
  const result = Number(p1h1)   Number(p1h2);

  return (
    <div>
      <input name="p1h1" value={input.p1h1} onChange={handleInput} type="number" min="0"></input>

      <input name="p1h2" value={input.p1h2} onChange={handleInput} type="number" min="0"></input>

      <h2>Result sum: {result}</h2>
    </div>
  );
};

CodePudding user response:

The way you are calling handleSum is not right. You should use a useEffect hook to re-render the element when a particular state changes as an array of dependencies (2nd argument of useEffect). You can learn more about it here https://reactjs.org/docs/hooks-effect.html.

const App = () => { 

const [input, setInput] = React.useState({
    p1h1: "",
    p1h2: "",
});
React.useEffect(() => {
    handleSum()
  }, [input])

const [result, setResult] = React.useState("")

//handle input change  
const handleInput = function(e){
    setInput({
        ...input, 
        [e.target.name]: e.target.value
    });
};

//handle sum
const handleSum = function(){
    const { p1h1, p1h2 } = input;            
    setResult(Number(p1h1)   Number(p1h2));
}
  return (
    <div>

      <input
        name= "p1h1" 
        value={input.p1h1} 
        onChange={handleInput} 
        type= "number" 
        min="0">
      </input>

      <input 
        name= "p1h2" 
        value={input.p1h2} 
        onChange={handleInput} 
        type= "number" 
        min="0">
      </input>
    <h2>Result sum: {result}</h2>
</div>

) }

CodePudding user response:

I've provided a working codesandbox for you to look at.

https://codesandbox.io/s/focused-pascal-ppyhz?file=/src/App.js:0-930

Good luck!

  • Related