我有一个无状态组件,我想重新渲染它。我怎么能这样做?我尝试使用forceUpdate
,但它没有用。
我可以改为使用forUpdate吗?
答案 0 :(得分:26)
使用反应挂钩,您现在可以在组件函数中调用useState()
。这将返回由2个元素组成的数组:一个值和一个“ setter”函数,可用于更新返回的第一个值,这样做将迫使您的函数组件重新呈现,就像forceUpdate
确实:
import React, { useState } from 'react';
//create your forceUpdate hook
function useForceUpdate(){
const [value, set] = useState(true); //boolean state
return () => set(!value); // toggle the state to force render
}
function MyComponent() {
// use your hook her
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函数。
答案 1 :(得分:12)
官方常见问题解答(https://reactjs.org/docs/hooks-faq.html#is-there-something-like-forceupdate)现在建议您确实需要这样做的方式:
const [ignored, forceUpdate] = useReducer(x => x + 1, 0);
function handleClick() {
forceUpdate();
}
答案 2 :(得分:7)
不,你不能,State-Less组件只是返回functions
的正常jsx
,你没有任何访问React生命周期方法的权限,因为你没有从{{1}扩展{1}}。
答案 3 :(得分:7)
我使用了一个名为 use-force-update 强制渲染我的反应功能组件。像魅力一样工作。 只需在您的项目中使用导入包并像这样使用即可。
import useForceUpdate from 'use-force-update';
const MyButton = () => {
const forceUpdate = useForceUpdate();
const handleClick = () => {
alert('I will re-render now.');
forceUpdate();
};
return <button onClick={handleClick} />;
};
答案 4 :(得分:1)
这可以在不显式使用钩子的情况下完成,前提是您要向组件中添加道具并向无状态组件的父组件添加状态:
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>
)
}
答案 5 :(得分:1)
可接受的答案是好的。 只是为了使其更易于理解。
示例组件:
export default function MyComponent(props) {
const [updateView, setUpdateView] = useState(0);
return (
<>
<span style={{ display: "none" }}>{updateView}</span>
</>
);
}
要强制重新渲染,请调用以下代码:
setUpdateView((updateView) => ++updateView);
答案 6 :(得分:0)
这些都没有给我一个满意的答案,所以最后我用 key
道具、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)
}
}
答案 7 :(得分:0)
最佳方法 - 在每次渲染时不会重新创建多余的变量:
const forceUpdateReducer = (i) => i + 1
export const useForceUpdate = () => {
const [, forceUpdate] = useReducer(forceUpdateReducer, 0)
return forceUpdate
}
用法:
const forceUpdate = useForceUpdate()
forceUpdate()
答案 8 :(得分:0)
如果您使用版本 < 16.8 的功能组件。一种解决方法是直接调用相同的函数,如
import React from 'react';
function MyComponent() {
const forceUpdate = MyComponent();
return (
<div>
<button onClick={forceUpdate}>
Click to re-render
</button>
</div>
);
}
但是如果你向它传递一些道具,这会中断。就我而言,我只是将收到的相同道具传递给重新渲染功能。
答案 9 :(得分:0)
你可以简单地这样做
如果您想启动重新渲染,请添加一个虚拟状态,您可以更改以启动重新渲染。
const [rerender, setRerender] = useState(false);
...
setRerender(!rerender); //whenever you want to re-render
这将确保重新渲染,因为组件在状态更改时重新渲染
答案 10 :(得分:-2)
免责声明:不是问题的答案。
在此处留下重要说明:
如果您试图强制更新无状态组件,则可能是您的设计有问题。
请考虑以下情况: