Home > Blockchain >  Arrow function does not use local variable inside component ReactJS
Arrow function does not use local variable inside component ReactJS

Time:10-28

I have got a trouble with updating an object inside React component with events.

const Comp = (props) => {
  ...
  let tango = {alpha: null};
  ...
  let handleFirst = () => {
    tango.alpha = "CLICK";
    console.log(tango);
  }

  let handleSecond = () => {
    console.log(tango);
  }

  return (
    <div id="first" onClick={handleFirst}>text</div>
    <div id="second" onClick={handleSecond}>image</div>
  )
}

When I click on div first I receive the following console output: {alpha: "CLICK"}, but when I click on div second I receive console output as it is null: {alpha: null}. I don't want to include tango into useState function because I want to update state of the component after another trigger, so I don't need to render component after each edit of object.
It seems to me very discouragingly but I don't know what to I've tried almost everything, and it seems to me to add alpha to state will be solution but I hope I can avoid it.

CodePudding user response:

It sounds like there's some some re-rendering in between the first click on the second - if there wasn't, the tango closed over by the handleFirst that gets invoked would be the same one closed over by the invoked handleSecond:

const Comp = (props) => {
  let tango = {alpha: null};
  let handleFirst = () => {
    tango.alpha = "CLICK";
    console.log(tango);
  }

  let handleSecond = () => {
    console.log(tango);
  }

  return (<div>
    <div id="first" onClick={handleFirst}>text</div>
    <div id="second" onClick={handleSecond}>image</div>
  </div>)
}

ReactDOM.render(<Comp />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

If you want to keep a persistent reference to tango across re-renders, without the change to it causing a re-render itself, you can use a ref instead:

const Comp = (props) => {
  let tangoRef = React.useRef({alpha: null});
  const [someState, setSomeState] = React.useState(0);
  let handleFirst = () => {
    tangoRef.current.alpha = "CLICK";
    setSomeState(someState   1);
    console.log(tangoRef.current);
  }

  let handleSecond = () => {
    console.log(tangoRef.current);
  }

  return (<div>
    <div id="first" onClick={handleFirst}>text</div>
    <div id="second" onClick={handleSecond}>image</div>
  </div>)
}

ReactDOM.render(<Comp />, document.querySelector('.react'));
<script crossorigin src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div class='react'></div>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

  • Related