我有一个函数组件,我想强制它重新渲染。
我该怎么做呢? 因为没有实例this,所以我不能调用this. forceupdate()。
我有一个函数组件,我想强制它重新渲染。
我该怎么做呢? 因为没有实例this,所以我不能调用this. forceupdate()。
当前回答
更新react v16.8(2019年2月16日发布)
由于react 16.8发布了钩子,函数组件有能力保持持久状态。有了这个能力,你现在可以模仿一个forceUpdate:
function App() { const [, updateState] = React.useState(); const forceUpdate = React.useCallback(() => updateState({}), []); console.log("render"); return ( <div> <button onClick={forceUpdate}>Force Render</button> </div> ); } const rootElement = document.getElementById("root"); ReactDOM.render(<App />, rootElement); <script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.1/umd/react.production.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.1/umd/react-dom.production.min.js"></script> <div id="root"/>
请注意,这种方法应该重新考虑,在大多数情况下,当您需要强制更新时,您可能会做错一些事情。
react 16.8.0之前
不,你不能,无状态函数组件只是返回jsx的普通函数,你没有任何访问React生命周期方法的权限,因为你没有从React. component扩展。
可以将function-component看作类组件的呈现方法部分。
其他回答
如果您正在使用版本< 16.8的功能组件。一种解决方法是直接调用相同的函数
import React from 'react';
function MyComponent() {
const forceUpdate = MyComponent();
return (
<div>
<button onClick={forceUpdate}>
Click to re-render
</button>
</div>
);
}
但如果你给它一些支撑,它就会断裂。在我的情况下,我只是通过相同的道具,我收到了渲染功能。
最佳方法-没有多余的变量重新创建在每次渲染:
const forceUpdateReducer = (i) => i + 1
export const useForceUpdate = () => {
const [, forceUpdate] = useReducer(forceUpdateReducer, 0)
return forceUpdate
}
用法:
const forceUpdate = useForceUpdate()
forceUpdate()
官方常见问题现在推荐这种方式,如果你真的需要这样做:
const [ignored, forceUpdate] = useReducer(x => x + 1, 0);
function handleClick() {
forceUpdate();
}
我使用了一个第三方库 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} />;
};
这些都没有给我一个满意的答案,所以最后我得到了我想要的关键道具,useRef和一些随机id生成器,如shortid。
基本上,我想要一些聊天应用在别人第一次打开应用时发挥自己的作用。所以,我需要完全控制什么时候和什么答案更新与异步等待的易用性。
示例代码:
function sleep(ms) {
return new Promise(resolve => setTimeout(resolve, ms));
}
// ... your JSX functional component, import shortid somewhere
const [render, rerender] = useState(shortid.generate())
const messageList = useRef([
new Message({id: 1, message: "Hi, let's get started!"})
])
useEffect(()=>{
async function _ () {
await sleep(500)
messageList.current.push(new Message({id: 1, message: "What's your name?"}))
// ... more stuff
// now trigger the update
rerender(shortid.generate())
}
_()
}, [])
// only the component with the right render key will update itself, the others will stay as is and won't rerender.
return <div key={render}>{messageList.current}</div>
事实上,这也允许我滚动一些像聊天信息滚动。
const waitChat = async (ms) => {
let text = "."
for (let i = 0; i < ms; i += 200) {
if (messageList.current[messageList.current.length - 1].id === 100) {
messageList.current = messageList.current.filter(({id}) => id !== 100)
}
messageList.current.push(new Message({
id: 100,
message: text
}))
if (text.length === 3) {
text = "."
} else {
text += "."
}
rerender(shortid.generate())
await sleep(200)
}
if (messageList.current[messageList.current.length - 1].id === 100) {
messageList.current = messageList.current.filter(({id}) => id !== 100)
}
}