this[field] alternative in Hooks

Viewed 250

There is a very convinient way to store some render-independent data in React Class by creating a field for it.

For example, if I making several forms, each appearing only at certain step and want to save its data after each step, in Class I will do this:

/*in class*/

data = [];

saveData = (field) => {
  this.data.push(field);
};

But how can I do the same in functional component if there is no "this", and all scope variables re-creating on each render?

2 Answers

For render-independent-data, the recommended way is to use a ref. The useRef hook exposes an object whose current property is mutable, you can attach any values that you want persisted across re-renders to it.

const data = useRef([]);  // <-- initial value

saveData = (field) => {
  this.data.current.push(field);
};

The main issue of using a simple variable in a functional component is that it will reinitialized on each render. You can solve this problem with useRef, since the data is retained when the component rerenders, and changing it doesn't cause rerender.

Click add several times, and then click render (forcing render via useState);

const { useState, useRef } = React;

const Demo = () => {
  const [v, render] = useState(0);
  
  const data = useRef([]);
  
  const saveData = (field) => {
    data.current.push(field);
  };

  return (
    <div>
      <button onClick={() => render(Math.random())}>Render</button>
      
      <button onClick={() => saveData(1)}>Add</button>
      
      <div>
        {data.current.toString()}    
      </div>
    </div>  
  );
};

ReactDOM.render(
  <Demo />,
  root
);
<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 id="root"></div>

Related