React-select v3.1.0选中项不显示及Strict Mode警告问题排查
React-select 选中值不显示+state更新问题解决方案
问题拆解
你碰到的问题主要有三个:
- 选中选项后,下拉输入框不显示选中值,明明
handleChange能触发,打印的选中信息也正确,但setState后state里的selectTry还是空对象(其实是setState异步特性导致的错觉) - React严格模式下出现
findDOMNode不该被调用的警告 - 需要实现默认选中第一个经销商的需求
核心原因&修复步骤
1. 输入框不显示选中值的关键原因
你代码里设置了controlShouldRenderValue={false},这个属性的作用就是隐藏选中值在输入框的显示,把它删掉或者改成true(默认就是true,所以直接删掉就行);另外,你给value传的是this.state.selectTry.value,但React-select的value属性需要接收完整的选项对象(包含value和label两个字段),不是单独的value值。
2. 解决state更新后看似没变化的问题
setState是异步操作,你在调用setState后立刻打印this.state肯定拿不到最新值,要在setState的回调函数里查看更新后的state:
handleChange = (info: any) => { this.setState({ selectTry: info }, () => { console.log('更新后的selectTry:', this.state.selectTry); // 这里才能看到最新值 }); }
3. 实现默认选中第一个经销商
因为我们用的是受控组件(通过state的value控制选中状态),所以defaultValue会被忽略,正确的做法是在组件初始化或者拿到dealers数据后,把selectTry初始化为第一个经销商的对象:
- 如果dealers是在组件挂载时就从props拿到的,可以在
componentDidMount里初始化:
componentDidMount() { const { dealers } = this.props; // 或者从this.state取,看你的数据存在哪 if (dealers && dealers.length > 0) { this.setState({ selectTry: { value: dealers[0].dealerId, label: dealers[0].name } }); } }
- 如果dealers是通过异步请求获取的,可以在请求完成后更新state时同时设置
selectTry的初始值。
修改后的完整Select代码
{dealers && dealers.length > 0 ? ( <Select backspaceRemovesValue={false} // 删掉controlShouldRenderValue={false},让选中值正常显示 hideSelectedOptions={false} isClearable={false} onChange={(value) => this.handleChange(value)} options={dealers.map((data: any) => ({ value: data.dealerId, label: data.name }))} tabSelectsValue={false} value={this.state.selectTry} // 传递完整的选项对象 /> ) : null}
关于严格模式下的findDOMNode警告
React-select 3.x版本内部确实使用了findDOMNode,这在React严格模式下会触发警告。解决办法有两个:
- 最彻底的:升级到React-select 4.x及以上版本,这个版本已经移除了
findDOMNode的使用,同时API变化不大,你的代码基本不需要大改 - 暂时妥协:如果不想升级,可以忽略这个警告,或者用一个简单的包装组件来规避,但效果不如升级彻底
内容的提问来源于stack exchange,提问作者Pradip Hinge
相关产品推荐
相关产品推荐

