我有一个功能组件,我想强迫它重新渲染。
我该怎么办?
由于没有实例this
,因此我无法致电this.forceUpdate()
。
我有一个功能组件,我想强迫它重新渲染。
我该怎么办?
由于没有实例this
,因此我无法致电this.forceUpdate()
。
Answers:
现在,使用react挂钩,您可以调用useState()
函数组件。
useState()
将返回由2个元素组成的数组:
1.一个值,表示当前状态。
2.它的二传手。用它来更新值。
通过其设置程序更新值将迫使您的功能组件重新呈现,
就像这样forceUpdate
做:
import React, { useState } from 'react';
//create your forceUpdate hook
function useForceUpdate(){
const [value, setValue] = useState(0); // integer state
return () => setValue(value => ++value); // update the state to force render
}
function MyComponent() {
// call your hook here
const forceUpdate = useForceUpdate();
return (
<div>
{/*Clicking on the button will force to re-render like force update does */}
<button onClick={forceUpdate}>
Click to re-render
</button>
</div>
);
}
上面的组件使用了自定义的钩子函数(useForceUpdate
),该函数使用了布尔状态钩子(useState
)。它切换布尔状态,从而告诉React重新运行render函数。
在此答案的旧版本中,代码段使用布尔值,并将其切换为forceUpdate()
。现在,我已经编辑了答案,该代码段使用数字而不是布尔值。
为什么呢 (你会问我)
因为发生在我身上的forceUpdate()
是,后来又从2个不同的事件中两次调用了my ,因此将布尔值重置为其原始状态,并且组件从未呈现。
因为在useState
的setter(setValue
此处)中,React
将之前的状态与新的状态进行比较,并且仅在状态不同时才进行渲染。
forceUpdate
。
useState
钩子,而不是类,setState
它实际上并不能进行比较(除非您实现了shouldUpdate方法)。看到我发布的同一演示,但是使用的静态值setState
,它不会再次呈现:codesandbox.io/s/determined-rubin-8598l
更新react v16.8(2019年2月16日实现)
由于使用钩子发布了react 16.8,因此功能组件现在可以保持持久性state
。有了这种能力,你现在可以模仿一个forceUpdate
:
请注意,应该重新考虑这种方法,并且在大多数情况下,当您需要强制执行更新时,您可能做错了什么。
反应之前16.8.0
不行,State-Less函数组件只是functions
返回的正常对象jsx
,您没有访问React生命周期方法的权限,因为您没有从扩展React.Component
。
将功能组件视为render
类组件的方法部分。
props
或state
更改的情况下。您无法强制渲染功能,因为render
无状态组件上没有功能。无状态组件并非extends
React.Component
仅仅是返回的简单函数jsx
。
现在,如果您确实需要这样做,则官方常见问题解答(https://reactjs.org/docs/hooks-faq.html#is-there-something-like-forceupdate)建议采用这种方式:
const [ignored, forceUpdate] = useReducer(x => x + 1, 0);
function handleClick() {
forceUpdate();
}
const [, forceUpdate] = useReducer(x => x + 1, 0);
我使用了一个名为use-force-update的第三方库 来强制渲染我的React功能组件。像魅力一样工作。只需在项目中使用import包并使用即可。
import useForceUpdate from 'use-force-update';
const MyButton = () => {
const forceUpdate = useForceUpdate();
const handleClick = () => {
alert('I will re-render now.');
forceUpdate();
};
return <button onClick={handleClick} />;
};
useForceUpdate
使用useCallback
其他答案中提到的方法。该库只是一个实用程序库,可以节省一些击键。
免责声明:并非问题的答案。
在此处留下重要说明:
如果您试图强制更新无状态组件,则可能是您的设计有问题。
考虑以下情况:
无需显式使用钩子即可完成此操作,前提是您向组件添加了prop,向无状态组件的父组件添加了状态:
const ParentComponent = props => {
const [updateNow, setUpdateNow] = useState(true)
const updateFunc = () => {
setUpdateNow(!updateNow)
}
const MyComponent = props => {
return (<div> .... </div>)
}
const MyButtonComponent = props => {
return (<div> <input type="button" onClick={props.updateFunc} />.... </div>)
}
return (
<div>
<MyComponent updateMe={updateNow} />
<MyButtonComponent updateFunc={updateFunc}/>
</div>
)
}
接受的答案是好的。只是为了使其更容易理解。
示例组件:
export default function MyComponent(props) {
const [updateView, setUpdateView] = useState(0);
return (
<>
<span style={{ display: "none" }}>{updateView}</span>
</>
);
}
要强制重新渲染,请调用以下代码:
setUpdateView((updateView) => ++updateView);