Reactjs 从状态初始化的react final form中带有react select的条件下拉列表
我使用Reactjs 从状态初始化的react final form中带有react select的条件下拉列表,reactjs,react-select,react-final-form,react-final-form-arrays,Reactjs,React Select,React Final Form,React Final Form Arrays,我使用react select和react final form作为条件下拉列表,其中第二个选择的选项由组件根据第一个选择的值提供(由于如此) 以下是组件: /** Changes options and clears field B when field A changes */ const PickOptions = ({ a, b, optionsMap, children }) => { const aField = useField(a, { subscription: {
react select
和react final form
作为条件下拉列表,其中第二个选择的选项由
组件根据第一个选择的值提供(由于如此)
以下是组件:
/** Changes options and clears field B when field A changes */
const PickOptions = ({ a, b, optionsMap, children }) => {
const aField = useField(a, { subscription: { value: 1 } });
const bField = useField(b, { subscription: {} });
const aValue = aField.input.value.value;
const changeB = bField.input.onChange;
const [options, setOptions] = React.useState(optionsMap[aValue]);
React.useEffect(() => {
changeB(undefined); // clear B
setOptions(optionsMap[aValue]);
}, [aValue, changeB, optionsMap]);
return children(options || []);
};
// subscibe to keep track of aField has been changed
const aFieldSubscription = useField(a, { subscription: { dirty: 1 } });
React.useEffect(() => {
setOptions(optionsMap[aValue]);
if (optionsMap[aValue]) {
// set of bValues defined in array
const bValueSet = optionsMap[aValue].filter(x => x.type === optionType);
if (aFieldSubscription.meta.dirty) {
changeB(bValueSet[0]); // change B
}
}
}, [aValue, changeB, optionsMap]);
当第一个选择的值更改为changeB(未定义)
时,它将清除第二个选择。我还通过传递initialValue
将第二个select设置为数组中的第一个选项。由于需要从状态中初始化值,因此我最终得到以下代码:
initialValue={
this.state.data.options[index] &&
this.state.data.options[index].secondOption
? this.state.data.options[index]
.secondOption
: options.filter(
option => option.type === "option"
)[0]
}
但它不起作用。状态的初始值不会传递到由
呈现的字段。如果我从组件中删除changeB(未定义)
,则会传递值,但当第一次选择的值更改时(即使选项已更新),第二次选择的输入值不会更新。这是我的网站的链接
如何修复它?我可以通过获取由
fields.map()
部分映射的所有内容,并将其包装到自己的组件中,以确保每个字段都有单独的状态,从而实现此功能。然后,我只是将changeB(undefined)
函数放在useffect
钩子的返回调用中,以便在用户为第一次选择选择不同的选项后清除辅助选择,如下所示:
React.useEffect(() => {
setOptions(optionsMap[aValue]);
return function cleanup() {
changeB(undefined) // clear B
};
}, [aValue, changeB, optionsMap]);
您可以在这个沙箱中看到它是如何工作的:
要更改辅助选择字段,您需要为数组对应的选项类型向PickOptions
传递一个额外的道具。我还订阅并跟踪上一个bValue
,以检查它是否存在于当前bValueSet
数组中。如果它存在,我们就不去管它,否则我们用它对应的optionType
数组中的第一个值来更新它
// subscibe to keep track of previous bValue
const bFieldSubscription = useField(b, { subscription: { value: 1 } })
const bValue = bFieldSubscription.input.value.value
React.useEffect(() => {
setOptions(optionsMap[aValue]);
if (optionsMap[aValue]) {
// set of bValues defined in array
const bValueSet = optionsMap[aValue].filter(x => x.type === optionType);
// if the previous bValue does not exist in the current bValueSet then changeB
if (!bValueSet.some(x => x.value === bValue)) {
changeB(bValueSet[0]); // change B
}
}
}, [aValue, changeB, optionsMap]);
下面是该方法的沙箱:
我还将您的类组件更改为函数式组件,因为我更容易查看和测试正在发生的事情,但这种方法也应该适用于您的类组件。基于前面的答案,我在组件中使用了以下代码:
/** Changes options and clears field B when field A changes */
const PickOptions = ({ a, b, optionsMap, children }) => {
const aField = useField(a, { subscription: { value: 1 } });
const bField = useField(b, { subscription: {} });
const aValue = aField.input.value.value;
const changeB = bField.input.onChange;
const [options, setOptions] = React.useState(optionsMap[aValue]);
React.useEffect(() => {
changeB(undefined); // clear B
setOptions(optionsMap[aValue]);
}, [aValue, changeB, optionsMap]);
return children(options || []);
};
// subscibe to keep track of aField has been changed
const aFieldSubscription = useField(a, { subscription: { dirty: 1 } });
React.useEffect(() => {
setOptions(optionsMap[aValue]);
if (optionsMap[aValue]) {
// set of bValues defined in array
const bValueSet = optionsMap[aValue].filter(x => x.type === optionType);
if (aFieldSubscription.meta.dirty) {
changeB(bValueSet[0]); // change B
}
}
}, [aValue, changeB, optionsMap]);
通过这种方式,它会检查用户是否更改了“远场”,如果是,它会将“远场”的值设置为数组中的第一个选项。非常感谢您的回复!我会试试看。但我还需要在更改第一个选择后,将第二个选择设置为数组中的第一个选项。仅当用户手动更改字段时,而不是从状态初始化表单时,才会发生这种情况。请参阅上面示例中的
initialValue
代码。@jupiteror我已修改了我的答案,以解决我认为您期望的结果。检查第二个沙盒链接。谢谢!但第二个示例中的值现在未初始化(这就是问题所在,我正在努力解决。@jupiteror很抱歉,我一定没有正确保存它,请再次尝试第二个示例。当您移动第一个选项时,值应该初始化并更改。现在还有两个问题。第一,当您尝试添加新选项时,应用程序崩溃。第二,第二个选项中的值始终为设置为数组中的第一个选项,而不是状态中的选项。第二个字段中的第二个选项应该是两个B,但它是两个A。