请参见下面的代码段,getInitialState
在每个渲染器上执行。即使从它返回的值仅在第一次渲染期间使用。
我知道这是正常的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"/>
答案 0 :(得分:2)
请勿直接在useState
内部调用该函数,而应传递一个匿名函数来触发该函数。请参阅官方Doc。
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"/>
答案 1 :(得分:0)
尝试使用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" />
答案 2 :(得分:0)
您需要根据docs在函数内部计算状态:
const [myState,setMyState] = useState(() => {
const initialState = getInitialState();
return initialState;
});
还有另一个陷阱!
答案 3 :(得分:0)
所有好的解决方案,我的两分钱=多米尼克在上面的简短解决方案。 :)
您要传递一个计算函数(该函数的结果传递给useState),如果您传递该函数,React知道它仅需要在第一次调用该函数:
function App() {
function getInitialState() {
console.log('Executing getInitialState...');
return({
foo: 'bar'
});
}
const [myState,setMyState] = React.useState(getInitialState); // <-- pass the function, not the call to the function (result)
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"/>