为什么useState挂钩两次调用初始化值代码?

时间:2019-08-16 12:55:46

标签: reactjs react-hooks

说我们有以下代码:

const [obj, setobj] = useState(generateInitialObj());

为什么发生generateInitialObj()被调用两次的情况?我已经将日志记录添加到generateInitialObj()中,我刚刚注意到了它。它似乎发生在组件生命周期的最开始。但是,一旦有反应从那里获得价值,我就会永远留在那里。无需重新获取它。 有什么想法吗?

3 个答案:

答案 0 :(得分:2)

这是JavaScript技术。 React无法阻止每个单独的渲染调用var receta = this.BindingContext; 。为了解决这个问题,React改为支持以下API:

generateInitialObj

答案 1 :(得分:0)

我认为组件的re-rendering是其背后的原因。您可以发布组件层次结构吗?

也可以尝试以下方法:

const [obj, setobj] = useState(() => generateInitialObj());

这是一个工作示例: https://stackblitz.com/edit/react-mysrjp

答案 2 :(得分:0)

经过测试并确认,如果您使用函数调用getInitialState(),那么它将每次都被调用,因为它确实是正常的JS行为。

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

function App() {
  console.log('Rendering App...');
  const [myState,setMyState] = React.useState(getInitialState());
  const [myBoolean,setMyBoolean] = React.useState(false);
  
  function updateApp() {
    setMyBoolean((prevState) => !prevState);
  }
  
  function changeAppState() {
    setMyState({
      propA: 'foo2',
      propB: 'bar2'
    });
  }
  
  return(
    <React.Fragment>
      <div>myState.propA: {myState.propA}</div>
      <div>myState.propB: {myState.propB}</div>
      <button onClick={updateApp}>Update App</button>
      <button onClick={changeAppState}>Change App State</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"/>

但是,如果您改用函数声明()=>getInitialState(),则它将仅被调用一次。

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

function App() {
  console.log('Rendering App...');
  const [myState,setMyState] = React.useState(()=>getInitialState());
  const [myBoolean,setMyBoolean] = React.useState(false);
  
  function updateApp() {
    setMyBoolean((prevState) => !prevState);
  }
  
  function changeAppState() {
    setMyState({
      propA: 'foo2',
      propB: 'bar2'
    });
  }
  
  return(
    <React.Fragment>
      <div>myState.propA: {myState.propA}</div>
      <div>myState.propB: {myState.propB}</div>
      <button onClick={updateApp}>Update App</button>
      <button onClick={changeAppState}>Change App State</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"/>

除此之外,两者的工作原理相同。