React中AutoComplete组件获取最终输入值的正确方式及状态错误排查
React Autocomplete组件"Cannot update during state transition"错误解决
问题背景
你在使用React Autocomplete组件时触发了Cannot update during state transition错误,排查后发现问题出在renderInput的实现代码里。原本想在renderInput中读取输入值,通过修改alleenUnCodes状态来过滤选项,但这个阶段属于组件渲染流程,此时调用setState会打断状态过渡,导致错误。同时你希望仅在用户真正选中选项时(比如点击弹窗选项、选中高亮选项按回车)执行对应方法。
原问题代码:
public render() { const { classes } = this.props; return ( <div className={classes.autoSuggest}> <Autocomplete ListboxProps={{ style: { maxHeight: 200, overflow: 'auto' } }} autoHighlight={true} disablePortal={false} options={this.getOptions()} onClick={(_event, value) => this.onSelect(value)} renderInput={(input) => { return this.onInput(input);}} /> </div> ); } private onInput(input: AutocompleteRenderInputParams) { if (!this.state.alleenUnCodes && input.inputProps.value !== undefined && input.inputProps.value.toString() !== "" && input.inputProps.value.toString().charAt(0) === '/') { this.setState({alleenUnCodes: true}); } if (this.state.alleenUnCodes && input.inputProps.value !== undefined && input.inputProps.value.toString().charAt(0) !== '/') { this.setState({alleenUnCodes: false}); } return <TextField {...input} label={'Type GEVI/UN of /UN code (bv 20/1002, of /20)'}/>; }
错误原因
renderInput是Autocomplete组件渲染流程的一部分,在这个阶段调用setState会触发额外的重新渲染,违反React的状态更新时机规则,因此抛出Cannot update during state transition错误。
解决方法
不需要在renderInput里通过修改状态来过滤选项,Autocomplete组件本身提供了filterOptions参数,可以直接用它实现自定义过滤逻辑;同时通过onChange(或组件的onSelect)处理用户选中选项的操作,确保仅在用户确认选中时执行对应方法。
修改后的代码示例:
public render() { const { classes } = this.props; return ( <div className={classes.autoSuggest}> <Autocomplete ListboxProps={{ style: { maxHeight: 200, overflow: 'auto' } }} autoHighlight={true} disablePortal={false} options={this.getOptions()} // 用户选中选项时执行逻辑 onChange={(_event, value) => this.onSelect(value)} // 自定义选项过滤逻辑 filterOptions={(options, state) => { const inputValue = state.inputValue || ''; // 根据输入值开头是否为'/'来过滤选项 if (inputValue.startsWith('/')) { // 替换成你的UN code过滤逻辑 return options.filter(option => option.includes('UN')); } else { // 替换成你的GEVI/UN过滤逻辑 return options.filter(option => option.includes('GEVI') || option.includes('UN')); } }} renderInput={(input) => ( <TextField {...input} label={'Type GEVI/UN of /UN code (bv 20/1002, of /20)'}/> )} /> </div> ); } private onSelect(value: /* 替换成你的选项类型 */) { // 真正选中值时执行的业务逻辑 }
关键调整说明
- 移除了
renderInput中调用setState的逻辑,避免在渲染阶段修改状态触发错误 - 使用
filterOptions直接根据输入值动态过滤选项,无需维护额外的alleenUnCodes状态 - 通过
onChange处理用户选中选项的操作,确保只有在用户确认选中(点击选项、按回车选中高亮项)时才执行对应逻辑
内容的提问来源于stack exchange,提问作者JasperMW
相关产品推荐
相关产品推荐

