【问题标题】:Force a single re-render with useSelector使用 useSelector 强制重新渲染
【发布时间】:2020-03-17 23:33:16
【问题描述】:

这是Refactoring class component to functional component with hooks, getting Uncaught TypeError: func.apply is not a function的后续行动

我已经声明了一个功能组件参数,它使用 useSelector 钩子从动作/reducers 中提取值:

const Parameter = () => {
let viz = useSelector(state => state.fetchDashboard);
const parameterSelect = useSelector(state => state.fetchParameter)
const parameterCurrent = useSelector(state => state.currentParameter)
const dispatch = useDispatch();
const drawerOpen = useSelector(state => state.filterIconClick);

const handleParameterChange = (event, valKey, index, key) => {
    parameterCurrent[key] = event.target.value;
    return (
        prevState => ({
            ...prevState,
            parameterCurrent: parameterCurrent
        }),
        () => {
            viz
                .getWorkbook()
                .changeParameterValueAsync(key, valKey)
                .then(function () {
                    //some code describing an alert
                    });
                })

                .otherwise(function (err) {
                    alert(
                        //some code describing a different alert
                    );
                });
        }
    );
};
const classes = useStyles();
return (
    <div>
        {drawerOpen ? (
            Object.keys(parameterSelect).map((key, index) => {
                return (
                    <div>
                        <FormControl component="fieldset">
                            <FormLabel className={classes.label} component="legend">
                                {key}
                            </FormLabel>
                            {parameterSelect[key].map((valKey, valIndex) => {
                                return (
                                    <RadioGroup
                                        aria-label="parameter"
                                        name="parameter"
                                        value={parameterCurrent[key]}//This is where the change should be reflected in the radio button
                                        onChange={(e) => dispatch(
                                            handleParameterChange(e, valKey, index, key)
                                        )}
                                    >
                                        <FormControlLabel
                                            className={classes.formControlparams}
                                            value={valKey}
                                            control={
                                                <Radio
                                                    icon={
                                                        <RadioButtonUncheckedIcon fontSize="small" />
                                                    }
                                                    className={clsx(
                                                        classes.icon,
                                                        classes.checkedIcon
                                                    )}
                                                />
                                            }
                                            label={valKey}
                                        />
                                    </RadioGroup>
                                );
                            })}
                        </FormControl>
                        <Divider className={classes.divider} />
                    </div>
                );
            })
        ) : (
                <div />
            )
        }
    </div >
)
};
export default Parameter;

我需要做的是让 value={parameterCurrent[key]} 在 handleParameterChange 上重新呈现(handleChange 确实会更新底层仪表板数据,但在我关闭主组件之前,单选按钮不会显示为被选中并重新打开它)。我以为我有一个强制重新渲染的解决方案,但是因为这是一个较小的组件,它是较大组件的一部分,所以它破坏了组件的其他部分(即它正在重新渲染并阻止其他组件获取来自 它的 reducer 的状态/道具)。我已经在互联网上搜索了 2 天的解决方案,但还没有找到任何可行的方法。任何帮助真的很感激!蒂亚!

【问题讨论】:

    标签: javascript reactjs react-hooks


    【解决方案1】:

    useSelector() 默认使用严格的=== 引用相等检查,而不是浅相等。

    要使用浅相等检查,请使用此

    import { shallowEqual, useSelector } from 'react-redux'
    
    const selectedData = useSelector(selectorReturningObject, shallowEqual)
    
    

    Read more

    【讨论】:

    • 谢谢,维杰!不幸的是,这似乎并没有解决问题。但是,我会阅读您链接中的信息,看看是否有什么可以做到的。
    【解决方案2】:

    好的,经过大量迭代,我找到了一种让它工作的方法(我确信这不是最漂亮或最有效的,但它确实有效,所以我会用它)。我已经发布了代码,并在下面进行了更改。

    我在声明整体 Parameter 函数时添加了 updateState 和 forceUpdate 行:

    const Parameter = () => {
    let viz = useSelector(state => state.fetchDashboard);
    const parameterSelect = useSelector(state => state.fetchParameter)
    const parameterCurrent = useSelector(state => state.currentParameter);
    const [, updateState] = useState();
    const forceUpdate = useCallback(() => updateState({}), []);
    const dispatch = useDispatch();
    const drawerOpen = useSelector(state => state.filterIconClick);
    

    然后在此处添加 forceUpdate() 行:

    const handleParameterChange = (event, valKey, index, key) => {
    parameterCurrent[key] = event.target.value;
    return (
        prevState => ({
            ...prevState,
            parameterCurrent: parameterCurrent
        }),
        () => {
            viz
                .getWorkbook()
                .changeParameterValueAsync(key, valKey)
                .then(function () {
                    //some code describing an alert
                    });
                })
    
                .otherwise(function (err) {
                    alert(
                        //some code describing a different alert
                    );
                });
    forceUpdate() //added here
        }
    );
    

    };

    然后在我想重新渲染的项目的 return 语句中调用 forceUpdate:

    <RadioGroup
                                            aria-label="parameter"
                                            name="parameter"
                                            value={forceUpdate, parameterCurrent[key]}//added forceUpdate here
                                            onChange={(e) => dispatch(
                                                handleParameterChange(e, valKey, index, key)
                                            )}
                                        >
    

    我已经对此进行了测试,它不会破坏任何其他代码。谢谢!

    【讨论】:

      猜你喜欢
      • 2022-11-17
      • 2020-06-27
      • 2021-12-30
      • 1970-01-01
      • 2014-07-27
      • 2022-01-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多