Hem*_*ari 38 javascript reactjs react-native react-hooks
考虑下面的钩子示例
import { useState } from 'react';
function Example() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
Run Code Online (Sandbox Code Playgroud)
基本上,我们使用this.forceUpdate()方法强制组件在React类组件中立即重新呈现,如下例所示
class Test extends Component{
constructor(props){
super(props);
this.state = {
count:0,
count2: 100
}
this.setCount = this.setCount.bind(this);//how can I do this with hooks in functional component
}
setCount(){
let count = this.state.count;
count = count+1;
let count2 = this.state.count2;
count2 = count2+1;
this.setState({count});
this.forceUpdate();
//before below setState the component will re-render immediately when this.forceUpdate() is called
this.setState({count2: count
}
render(){
return (<div>
<span>Count: {this.state.count}></span>.
<button onClick={this.setCount}></button>
</div>
}
}
Run Code Online (Sandbox Code Playgroud)
但是我的查询是如何强制上述功能组件立即使用钩子重新渲染?
Qwe*_*rty 45
通常,您可以使用任何想要触发更新的状态处理方法。
const forceUpdate: () => void = React.useState()[1].bind(null, {}) // see NOTE below
Run Code Online (Sandbox Code Playgroud)
const forceUpdate = React.useReducer(() => ({}), {})[1] as () => void
Run Code Online (Sandbox Code Playgroud)
只需像这样包装您喜欢的任何方法
function useForceUpdate(): () => void {
return React.useReducer(() => ({}), {})[1] as () => void // <- paste here
}
Run Code Online (Sandbox Code Playgroud)
“触发更新”的意思是告诉 React 引擎某些值已经改变,它应该重新渲染你的组件。
[, setState]fromuseState()需要一个参数。我们通过绑定一个新对象来摆脱它{}。
() => ({})inuseReducer是一个虚拟的reducer,每次分派动作时都会返回一个新对象。
{} (fresh object)是必需的,以便它通过更改状态中的引用来触发更新。
PS:useState只是在useReducer内部包装。来源
注意:将 .bind 与 useState 一起使用会导致渲染之间的函数引用发生变化。可以将它包装在 useCallback 中,正如这里已经解释的那样,但它不会是一个性感的 one-liner™。Reducer 版本已经在渲染之间保持引用相等。如果你想在 props 中传递 forceUpdate 函数,这很重要。
const forceUpdate = React.useState()[1].bind(null, {}) // see NOTE above
const forceUpdate = React.useReducer(() => ({}))[1]
Run Code Online (Sandbox Code Playgroud)
for*_*d04 34
React Hooks FAQ官方解决方案forceUpdate:
const [_, forceUpdate] = useReducer((x) => x + 1, 0);
// usage
<button onClick={forceUpdate}>Force update</button>
Run Code Online (Sandbox Code Playgroud)
const [_, forceUpdate] = useReducer((x) => x + 1, 0);
// usage
<button onClick={forceUpdate}>Force update</button>
Run Code Online (Sandbox Code Playgroud)
const App = () => {
const [_, forceUpdate] = useReducer((x) => x + 1, 0);
return (
<div>
<button onClick={forceUpdate}>Force update</button>
<p>Forced update {_} times</p>
</div>
);
};
ReactDOM.render(<App />, document.getElementById("root"));Run Code Online (Sandbox Code Playgroud)
nul*_*ook 27
替代@MinhKha 的回答:
它可以更清洁useReducer:
const [, forceUpdate] = useReducer(x => x + 1, 0);
Run Code Online (Sandbox Code Playgroud)
用法:
forceUpdate()- 没有参数的清洁器
Est*_*ask 24
可以使用useState或进行useReducer,因为在内部useState使用useReducer:
const [, updateState] = React.useState();
const forceUpdate = useCallback(() => updateState({}), []);
Run Code Online (Sandbox Code Playgroud)
forceUpdate不打算在正常情况下使用,仅在测试或其他出色情况下使用。可以以更常规的方式解决这种情况。
setCount是不当使用的一个例子forceUpdate。setState出于性能原因是异步的,不应仅由于状态更新未正确执行而被迫同步。如果状态依赖于先前设置的状态,则应使用updater函数来完成,
如果需要基于先前的状态来设置状态,请阅读以下有关updater参数的信息。
<...>
更新器功能接收到的状态和道具都保证是最新的。更新器的输出与state合并在一起。
setCount 可能不是说明性的示例,因为其用途尚不清楚,但updater函数就是这种情况:
setCount(){
this.setState(({count}) => ({ count: count + 1 }));
this.setState(({count2}) => ({ count2: count + 1 }));
this.setState(({count}) => ({ count2: count + 1 }));
}
Run Code Online (Sandbox Code Playgroud)
Gil*_*Dev 10
简单的代码
const forceUpdate = React.useReducer(bool => !bool)[1];
Run Code Online (Sandbox Code Playgroud)
用:
forceUpdate();
Run Code Online (Sandbox Code Playgroud)
As the others have mentioned, useState works - here is how mobx-react-lite implements updates - you could do something similar.
Define a new hook, useForceUpdate -
import { useState, useCallback } from 'react'
export function useForceUpdate() {
const [, setTick] = useState(0);
const update = useCallback(() => {
setTick(tick => tick + 1);
}, [])
return update;
}
Run Code Online (Sandbox Code Playgroud)
and use it in a component -
const forceUpdate = useForceUpdate();
if (...) {
forceUpdate(); // force re-render
}
Run Code Online (Sandbox Code Playgroud)
See https://github.com/mobxjs/mobx-react-lite/blob/master/src/utils.ts and https://github.com/mobxjs/mobx-react-lite/blob/master/src/useObserver.ts
潜在的选择是使用key. 更新密钥会触发组件的渲染(之前未能更新)
例如:
const [tableKey, setTableKey] = useState(1);
...
useEffect(() => {
...
setTableKey(tableKey + 1);
}, [tableData]);
...
<DataTable
key={tableKey}
data={tableData}/>
Run Code Online (Sandbox Code Playgroud)
您最好只让您的组件依赖状态和道具,并且它将按预期工作,但是如果您确实需要一个函数来强制重新渲染组件,则可以使用useStatehook并在需要时调用该函数。
例
const { useState, useEffect } = React;
function Foo() {
const [, forceUpdate] = useState();
useEffect(() => {
setTimeout(forceUpdate, 2000);
}, []);
return <div>{Date.now()}</div>;
}
ReactDOM.render(<Foo />, document.getElementById("root"));Run Code Online (Sandbox Code Playgroud)
<script src="https://unpkg.com/react@16.7.0-alpha.0/umd/react.production.min.js"></script>
<script src="https://unpkg.com/react-dom@16.7.0-alpha.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>Run Code Online (Sandbox Code Playgroud)
您可以(ab)使用普通钩子通过利用React 不会在 JSX 代码中打印布尔值这一事实来强制重新渲染
// create a hook
const [forceRerender, setForceRerender] = React.useState(true);
// ...put this line where you want to force a rerender
setForceRerender(!forceRerender);
// ...make sure that {forceRerender} is "visible" in your js code
// ({forceRerender} will not actually be visible since booleans are
// not printed, but updating its value will nonetheless force a
// rerender)
return (
<div>{forceRerender}</div>
)
Run Code Online (Sandbox Code Playgroud)
您可以像这样简单地定义useState:
const [, forceUpdate] = React.useState(0);
Run Code Online (Sandbox Code Playgroud)
和用法: forceUpdate(n => !n)
希望对您有所帮助!
react-tidy有一个专门用于执行此操作的自定义挂钩,称为useRefresh:
import React from 'react'
import {useRefresh} from 'react-tidy'
function App() {
const refresh = useRefresh()
return (
<p>
The time is {new Date()} <button onClick={refresh}>Refresh</button>
</p>
)
}
Run Code Online (Sandbox Code Playgroud)
免责声明我是这个库的作者。
| 归档时间: |
|
| 查看次数: |
33869 次 |
| 最近记录: |