这是我第一次使用React钩子将代码从类组件重构为功能组件的尝试。我们重构的原因是该组件当前使用即将失效的componentWillReceiveProps生命周期方法,而我们无法使其他生命周期方法按我们希望的方式工作。对于背景,原始组件具有上述的cWRP生命周期方法,handleChange函数,正在使用connect和mapStateToProps,并通过tableau API链接到Tableau仪表板的存储库。我还将具有四个不同功能的组件分解为自己的组件。我遇到的代码是这样的:
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;
分别定义了const类,并且所有的reducer等的输入都已完成。代码中的parameterSelect指向所有可用参数,而parameterCurrent指向在仪表板中选择的默认参数(即Viz最初加载的内容)。
正在发生两件事:1.初始Vizualization时一切正常,当我单击“单选按钮”更改参数时,我可以在仪表板上看到它的更新-但是,实际上并没有显示单选按钮为已选择(仍显示被初始化的那个参数)。 2.当我在“过滤器栏”(此组件被导入到的地方)之外单击时,出现Uncaught TypeError:func.apply不是一个函数。我重构了另一个组件,但没有出现这个问题,而且似乎无法确定在useEffect挂钩,handleParameterChange函数或return语句中的位置是否编码错误。此新手将不胜感激!
答案 0 :(得分:1)
要导入大量代码,却看不到原始类或没有要加载的代码沙箱。我最初的想法是可能是您的useEffect
在重构的代码中,您告诉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])
但是,此useEffect
似乎没有任何作用,因此,尽管其依赖项列表不正确,但我认为它不会解决您正在描述的问题。
我会看一下您的调度和选择器。仔细检查redux存储是否正在按预期进行更新,并且新值正在从change回调到存储,然后回退,并且不会因嵌套不正确,键名错误等而丢失... >
我建议发布CodeSandbox.io链接或原始类,以进行进一步的调试。