reactjs - React Select 与 Custom MultiValueContainer 和 Apollo Mutation 不合作
问题描述
我有一个使用 Apollo 和 React-Select 的自定义组件,并且有两个突变(见下文)。react-select 是多值的,需要自定义,因为我需要一个“isSelected”复选框。此代码中未显示,但初始选项列表是从父容器传入的。
父 Select 及其突变按预期工作。但是,我在使用自定义 MultiValueContainer 时遇到了一些奇怪的问题。首先是当我第一次选择任何复选框时,我收到一条错误消息,提示“无法在未安装的组件上调用 setState(或 forceUpdate)”。请注意,我有一个空的 componentWillUnmount 函数,只是为了查看它是否被调用,但它没有。但是(我假设)因此,当调用“toggleThing”突变时,状态没有完成请求所需的变量。我第二次单击它时按预期工作,但第二个问题除外。
第二个问题是 MultiValueContainer 突变上的 onCompleted 函数永远不会触发,因此即使服务器返回预期的数据,它似乎也永远不会回到突变,因此永远不会回到组件。父 Select 上的 onCompleted 函数按预期工作。
提前感谢任何人可能拥有的任何见解。也许不用说,我对 react/apollo/react-select 比较陌生,并为任何新手错误提前道歉。此外,我试图清理和简化代码,因此也为任何重命名错误道歉。
const UPDATE_THINGS = gql`
mutation UpdateThings(
$id: ID!
$newThings: [ThingInput]
) {
updateThings(
id: $id
newThings: $newThings
) {
id
}
}
`;
const TOGGLE_THING = gql`
mutation ToggleThing($id: ID!, $isChecked: Boolean) {
toggleThing(
id: $id
isChecked: $isChecked
) {
id
}
}
`;
class ThingList extends Component {
stylesObj = {
multiValue: base => {
return {
...base,
display: 'flex',
alignItems: 'center',
paddingLeft: '10px',
background: 'none',
border: 'none'
};
}
};
constructor(props) {
super(props);
this.state = {
selectedThings: [],
selectedThingId: '',
selectedThingIsChecked: false
};
}
onUpdateComplete = ({ updateThings }) => {
console.log('onUpdateComplete');
console.log('...data', updateThings );
this.setState({ selectedThings: updateThings });
};
onToggleThing = (thingId, isChecked, toggleThing) => {
console.log('onToggleThing, thingId, isChecked');
this.setState(
{
selectedThingId: thingId,
selectedThingIsChecked: isHighPisCheckedoficiency
},
() => toggleThing()
);
};
onToggleThingComplete = ({ onToggleThing }) => {
console.log('onToggleThingComplete ');
console.log('...data', onToggleThing );
this.setState({ selectedThings: onToggleThing });
};
handleChange = (newValue, actionMeta, updateThings) => {
this.setState(
{
selectedThings: newValue
},
() => updateThings()
);
};
isThingSelected = thing=> {
return thing.isSelected;
};
getSelectedThings = selectedThings => {
console.log('getSelectedSkills');
return selectedThings ? selectedThings.filter(obj => obj.isSelected) : [];
};
componentWillUnmount() {
console.log('componentWillUnmount');
}
render() {
const self = this;
const MultiValueContainer = props => {
// console.log('...props', props.data);
return (
<Mutation
mutation={ TOGGLE_THING }
onCompleted={self.onToggleThingComplete}
variables={{
id: self.state.selectedThingId,
isChecked: self.state.selectedThingIsChecked
}}>
{(toggleThing, { data, loading, error }) => {
if (loading) {
return 'Loading...';
}
if (error) {
return `Error!: ${error}`;
}
return (
<div className={'option d-flex align-items-center'}>
<input
type={'checkbox'}
checked={props.data.isChecked}
onChange={evt => {
self.onToggleThing(
props.data.id,
evt.target.checked,
toggleIsHighProficiency
);
}}
/>
<components.MultiValueContainer {...props} />
</div>
);
}}
</Mutation>
);
};
return (
<Mutation
mutation={UPDATE_THINGS}
onCompleted={this.onUpdateComplete}
variables={{ id: this.id, newThings: this.state.selectedThings}}>
{(updateThings, { data, loading, error }) => {
if (loading) {
return 'Loading...';
}
if (error) {
return `Error!: ${error}`;
}
return (
<div>
<Select
options={this.props.selectedThings}
styles={this.stylesObj}
isClearable
isDisabled={this.props.loading}
isLoading={this.props.loading}
defaultValue={this.props.selectedThings.filter(
obj => obj.isSelected
)}
isOptionSelected={this.isOptionSelected}
isMulti={true}
onChange={(newValue, actionMeta) =>
this.handleChange(
newValue,
actionMeta,
updateThings
)
}
components={{
MultiValueContainer
}}
/>
</div>
);
}}
</Mutation>
);
}
}
export default ThingsList;
解决方案
您正在重新定义MultiValueContainer
every render
,这不是一个好习惯,可能会导致意外行为。尝试将其移动到单独的组件中,看看是否有帮助。
推荐阅读
- android - 升级到 Android Gradle 插件 3.2 后,Gradle 构建中的 Findbugs 失败
- firefox - Firefox Quantum ESR PKCS11 - 如何通过脚本或配置设置加载
- pentaho - 最新版本的 pentaho 解决了 pentaho 8.1 中的 oracle 错误
- c# - 修改 IList 查询语句
- java - entityManager.remove(class) 不起作用
- php - 如何在不使用 PHP MVC 中的 Extend 的情况下将数据库操作层与 BaseModel 层分离?
- c# - 变量和垃圾回收的生命周期
- c# - 当 GoogleDriveApplication 托管在 IIS 服务器中时,无法启动浏览器
- ruby - 如何将嵌套的哈希参数传递给 searchkick
- visual-studio-code - VsCode:如何避免为每个编辑器组打开多个文件?