【发布时间】:2021-10-20 21:27:48
【问题描述】:
这个 react 的东西让我发疯了,我不记得很久以前我在做 react native 时遇到过这些问题。我在这里一定做错了什么,这是我遇到的问题之一,我有另一个组件也有类似的问题。我是新的新钩子系统,即使阅读了一些我仍然不太清楚的东西。
我遇到了一些本地状态和 redux 状态的问题,这些问题导致我的对话框闪烁。每次父组件在该循环中设置日志状态时,对话框都会关闭和打开。 (所以在这种情况下,100 次取决于循环长度)每次状态更新时都会重新渲染。
库 react/redux/redux-thunk/material-ui
示例代码
function ToolbarModal(props){
const [progressLog, setProgressLog] = useState("");
const openProgressDialog = useSelector(getOpenProgressDialog);
const handleCloseLongProgressDialog = () => {
dispatch(handleOpenBatchRouteProgressDialog(false))
}
const handleSomeLogic = () => {
for(let i=0; i<0; i++){
//The real one is concated with prev message
setProgressLog("SAMPLE MESSAGE")
}
}
return (
<div>
<LongProgressDialog
open={openProgressDialog}
onClose={handleCloseLongProgressDialog}
onEntered={handleSomeLogic}
log={progressLog}
/>
</div>
)
}
log prop 使用 material-ui 的对话框组件传递给子组件,并仅显示在文本字段中。
function LongProgressDialog(props){
const {open, onClose, onEntered, log} = props
return (
<Dialog
open={open}
onClose={onClose}
onEntered={onEntered}
maxWidth='sm'
fullWidth
>
<DialogTitle>Long Progress</DialogTitle>
<DialogContent>
<TextField
multiline
fullWidth
rows={10}
rowsMax={10}
variant='outlined'
disabled
value={log}
/>
</DialogContent>
</Dialog>
)
}
【问题讨论】:
-
每次调用
setProgressLog,都会更改状态变量并重新渲染组件。这就是反应组件的工作方式。如果你不想让组件重新渲染,为什么要使用状态变量? -
有没有办法只重新渲染 LongProgressDialog 中的文本字段,而不是重新渲染父级?因为我正在尝试从该逻辑函数重定向消息以慢慢建立日志。
-
不,如果文本字段在 LongProgressDialog 中,那么 LongProgressDialog 也必须重新渲染。虽然从那里你可以在 LongProgressDialog 的一些子组件上使用
React.memo之类的东西来阻止 他们 不必要地重新渲染(取决于他们收到的道具) -
当您更改状态时,组件会重新渲染,但在您的示例中,我认为这不是问题。如果您的对话框闪烁,这可能是您的 LongProgressDialog 组件中的问题。我认为您也应该共享该组件。如果在使用 setprograss 函数时 openProgressDialog 变量发生变化,则可能是 reducer 有问题。
-
你应该将forwardRef添加到LongProgressDialog,返回类似于changeText函数的东西。然后在ToolbarModal中,在LongProgressDialog的useRef对象中调用changeText
标签: reactjs redux material-ui redux-thunk