使用钩子将类组件重构为功能组件,得到 Uncaught TypeError: func.apply is not a function [英] Refactoring class component to functional component with hooks, getting Uncaught TypeError: func.apply is not a function

查看:125
本文介绍了使用钩子将类组件重构为功能组件,得到 Uncaught TypeError: func.apply is not a function的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我第一次尝试使用 React 钩子将代码从类组件重构为功能组件.我们重构的原因是该组件当前使用的是即将失效的 componentWillReceiveProps 生命周期方法,而我们无法让其他生命周期方法按我们想要的方式工作.作为背景,原始组件具有上述 cWRP 生命周期方法、handleChange 函数、使用 connect 和 mapStateToProps,并通过 tableau API 链接到 tableau 仪表板存储库.我还将具有四个不同功能的组件分解为它们自己的组件.我遇到问题的代码是这样的:

This is my first attempt to refactor code from a class component to a functional component using React hooks. The reason we're refactoring is that the component currently uses the soon-to-be-defunct componentWillReceiveProps lifecylcle method, and we haven't been able to make the other lifecycle methods work the way we want. For background, the original component had the aforementioned cWRP lifecycle method, a handleChange function, was using connect and mapStateToProps, and is linking to a repository of tableau dashboards via the tableau API. I am also breaking the component, which had four distinct features, into their own components. The code I'm having issues with is this:

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

useEffect(() => {
    let keys1 = Object.keys(parameterCurrent);
    if (
        keys1.length > 0 //if parameters are available for a dashboard
    ) {
        return ({
            parameterSelections: parameterCurrent
        });
    }
}, [props.parameterCurrent])

const handleParameterChange = (event, valKey, index, key) => {
    parameterCurrent[key] = event.target.value;
    console.log(parameterCurrent[key]);
    return (
        prevState => ({
            ...prevState,
            parameterSelections: parameterCurrent
        }),
        () => {
            viz
                .getWorkbook()
                .changeParameterValueAsync(key, valKey)
                .then(function () {
                    Swal.fire({
                        position: "center",
                        icon: "success",
                        title:
                            JSON.stringify(key) + " set to " + JSON.stringify(valKey),
                        font: "1em",
                        showConfirmButton: false,
                        timer: 2500,
                        heightAuto: false,
                        height: "20px"
                    });
                })

                .otherwise(function (err) {
                    alert(
                        Swal.fire({
                            position: "top-end",
                            icon: "error",
                            title: err,
                            showConfirmButton: false,
                            timer: 1500,
                            width: "16rem",
                            height: "5rem"
                        })
                    );
                });
        }
    );
};
const classes = useStyles();
return (
    <div>
        {Object.keys(parameterSelect).map((key, index) => {
            return (
                <div>
                    <FormControl component="fieldset">
                        <FormLabel className={classes.label} component="legend">
                            {key}
                        </FormLabel>
                        {parameterSelect[key].map((valKey, valIndex) => {
                            console.log(parameterSelections[key])
                            return (
                                <RadioGroup
                                    aria-label="parameter"
                                    name="parameter"
                                    value={parameterSelections[key]}
                                    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 >
)}; 
export default Parameter;

);})}</div >)};导出默认参数;

The classes const is defined separately, and all imports of reducers, etc. have been completed. parameterSelect in the code points to all available parameters, while parameterCurrent points to the default parameters chosen in the dashboard (i.e. what the viz initially loads with).

分别定义了const类,reducer等的所有导入都已经完成.代码中的 parameterSelect 指向所有可用的参数,而 parameterCurrent 指向仪表板中选择的默认参数(即可视化最初加载的内容).

Two things are happening: 1. Everything loads fine on initial vizualization, and when I click on the Radio Button to change the parameter, I can see it update on the dashboard - however, it's not actually showing the radio button as being selected (it still shows whichever parameter the viz initialized with as being selected). 2. When I click outside of the Filterbar (where this component is imported to), I get Uncaught TypeError: func.apply is not a function. I refactored another component and didn't have this issue, and I can't seem to determine if I coded incorrectly in the useEffect hook, the handleParameterChange function, or somewhere in the return statement. Any help is greatly appreciated by this newbie!!!

发生了两件事:1. 初始可视化时一切正常,当我单击单选按钮更改参数时,我可以在仪表板上看到它更新 - 但是,它实际上并未将单选按钮显示为选择(它仍然显示可视化初始化为被选择的任何参数).2. 当我在过滤器栏(此组件导入到的位置)外部单击时,我收到 Uncaught TypeError: func.apply is not a function.我重构了另一个组件并且没有这个问题,而且我似乎无法确定我是否在 useEffect 钩子、handleParameterChange 函数或 return 语句中的某处编码不正确.这个新手非常感谢任何帮助!!!

解决方案

推荐答案

在没有看到原始类或没有代码沙箱加载的情况下,需要接受大量代码.我最初的想法是它可能是你的 useEffect

In your refactored code, you tell your useEffect to only re-run when the props.parameterCurrent changes. However inside the useEffect you don't make use of props.parameterCurrent, you instead make use of parameterCurrent from the local lexical scope. General rule of thumb, any values used in the calculations inside a useEffect should be in the list of re-run dependencies.

在重构的代码中,您告诉 useEffect 仅在 props.parameterCurrent 更改时重新运行.但是,在 useEffect 中,您没有使用 props.parameterCurrent,而是使用本地词法范围中的 parameterCurrent.一般的经验法则,在 useEffect 内的计算中使用的任何值都应该在重新运行依赖项的列表中.

useEffect(() => { let keys1 = Object.keys(parameterCurrent); if ( keys1.length > 0 //if parameters are available for a dashboard ) { return ({ parameterSelections: parameterCurrent }); } }, [parameterCurrent])

However, this useEffect doesn't seem to do anything, so while its dependency list is incorrect, I don't think it'll solve the problem you are describing.

然而,这个 useEffect 似乎没有做任何事情,所以虽然它的依赖列表不正确,但我认为它不会解决你所描述的问题.

I would look at your dispatch and selector. Double check that the redux store is being updated as expected, and that the new value is making it from the change callback, to the store, and back down without being lost due to improper nesting, bad key names, etc...

我会查看您的调度和选择器.仔细检查 redux 存储是否按预期更新,并且新值正在从更改回调到存储,然后返回而不会因嵌套不当、键名错误等而丢失...

我建议发布 CodeSandbox.io 链接或原始类以进一步帮助调试.

I'd recommend posting a CodeSandbox.io link or the original class for further help debugging.

这篇关于使用钩子将类组件重构为功能组件,得到 Uncaught TypeError: func.apply is not a function的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆