Как избежать того, чтобы параметр функции useState (для получения начальных значений) выполнялся при каждом рендеринге? - PullRequest
0 голосов
/ 25 сентября 2019

Из приведенного ниже фрагмента см., Что getInitialState выполняется для каждого рендера.Хотя возвращаемое значение используется только во время 1-го рендеринга.

Я знаю, что это нормальное поведение Javascript.Но есть ли способ избежать этого с помощью React?

function App() {

  function getInitialState() {
    console.log('Executing getInitialState...');
    return({
      foo: 'bar'
    });
  }

  const [myState,setMyState] = React.useState(getInitialState());
  const [myBoolean,setMyBoolean] = React.useState(false);
  
  return(
    <React.Fragment>
      <div>I am App</div>
      <div>My state: {JSON.stringify(myState)}</div>
      <div>My boolean: {JSON.stringify(myBoolean)}</div>
      <button onClick={()=>setMyBoolean((prevState) => !prevState)}>Force Update</button>
    </React.Fragment>
  );
}

ReactDOM.render(<App/>, document.getElementById('root'));
<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="root"/>

Ответы [ 3 ]

2 голосов
/ 25 сентября 2019

Не вызывайте функцию непосредственно внутри useState, передайте анонимную функцию, чтобы вызвать функцию.Обратитесь к официальному Док .

  function getInitialState() {
    console.log('Executing getInitialState...');
    return({
      foo: 'bar'
    });
  }
  
function App() {

  const [myState,setMyState] = React.useState(()=>getInitialState());
  const [myBoolean,setMyBoolean] = React.useState(false);
  
  return(
    <React.Fragment>
      <div>I am App</div>
      <div>My state: {JSON.stringify(myState)}</div>
      <div>My boolean: {JSON.stringify(myBoolean)}</div>
      <button onClick={()=>setMyBoolean((prevState) => !prevState)}>Force Update</button>
    </React.Fragment>
  );
}

ReactDOM.render(<App/>, document.getElementById('root'));
<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="root"/>
0 голосов
/ 25 сентября 2019

Вам нужно вычислить ваше состояние внутри функции в соответствии с документами :

const [myState,setMyState] = useState(() => {
  const initialState = getInitialState();
  return initialState;
});

Еще один хук понял!

0 голосов
/ 25 сентября 2019

Попробуйте запомнить с помощью React.useMemo

function getInitialState() {
  console.log('Executing getInitialState...');
  return {
    foo: 'bar'
  };
}

function App() {
  const getInitial = React.useMemo(() => getInitialState(), []);
  const [myState, setMyState] = React.useState(getInitial);
  const [myBoolean, setMyBoolean] = React.useState(false);

  return (
    <React.Fragment>
      <div> I am App </div>
      <div> My state: {JSON.stringify(myState)} </div>
      <div> My boolean: {JSON.stringify(myBoolean)} </div>
      <button onClick={() => setMyBoolean(prevState => !prevState)}>
        Force Update
      </button>
    </React.Fragment>
  );
}

ReactDOM.render(<App />, document.getElementById('root'));
<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="root" />
...