React中如何将File2.js的selectedValue传递给File1.js的Pool变量
解决方案
核心问题排查
你的实现出现问题的根本原因有3个:
- Pool、datasets、data等变量定义在组件外部,属于顶层普通变量,React的状态更新机制无法感知这类变量的变化,也不会触发组件重渲染,就算值被修改也不会更新图表
- 状态归属错误:下拉选中值需要在父组件File1中使用,不应该存储在子组件DropdownMenu的内部state中,需要做状态提升
- 没有建立子组件到父组件的通信通道,父组件无法感知下拉框的选中变化,自然无法触发图表数据的重新计算
修改后代码
File1.js
import { useState, useMemo } from 'react'; import DropdownMenu from './File2'; // 按你的实际路径调整导入 const genes = ['CY5','ROX','HEX','FAM']; const amp_values = parser.amp_values; const colors = ['rgb(255,195,0)','rgb(32,243,31)','rgb(31,243,232)', 'rgb(238,31,243)']; const bdcolor = ['rgba(255,195,0,0.3)','rgba(32,243,31,0.3)','rgba(31,243,232,0.3)', 'rgba(238,31,243,0.3)']; const options = { scales: { yAxes: [ { ticks: { beginAtZero: true, }, }, ], xAxes: { display: false }, }, }; const LineChart = () => { // 把pool值存在父组件的state中,初始值为0 const [pool, setPool] = useState(0); // pool变化时自动重新计算图表数据 const data = useMemo(() => { const datasets = []; for(let j = 0; j < 4; j++) { datasets[j] = { label: genes[j], data: amp_values[j][pool], fill: false, backgroundColor: colors[j%colors.length], borderColor: bdcolor[j%bdcolor.length] } } return { labels: Array.from({length:45}, (_,i)=>i+1), datasets: datasets, } }, [pool]); // 依赖项为pool,pool变化时自动重新执行计算 return ( <> <div> <div className='header'> <h1>Gene Pooling Plot</h1> </div> <div className='menu'> {/* 把更新pool的方法传给子组件 */} <DropdownMenu onPoolChange={setPool}/> </div> <div > <Line className="chart" data={data} options={options} height='600' width='1000'/> </div> </div> </> ) }; export default LineChart;
File2.js
const options = parser.pool_listed; class DropdownMenu extends Component { constructor (props) { super(props) this.state = {selected: ''} this._onSelect = this._onSelect.bind(this) } _onSelect (option) { this.setState({selected: option}) // 选中后调用父组件传的回调,把选中值转成数字索引传出去 const value = typeof option === 'string' ? option : option.label; this.props.onPoolChange(Number(value)); } render () { const defaultOption = this.state.selected const selectedValue = typeof this.state.selected === 'string' ? defaultOption : this.state.selected.label return ( <section> <h3>Select pool value: </h3> <Dropdown options={options} onChange={this._onSelect} value={selectedValue} placeholder="Select an option"/> {selectedValue} </section> ) } } export default DropdownMenu;
原执行顺序问题的解决逻辑
修改后所有依赖下拉选中值的逻辑都绑定在父组件的pool状态上:
- 首次渲染时用初始值0生成图表数据
- 下拉框选中新值后,立即调用父组件传的
setPool更新父组件状态 - 父组件状态更新后,自动触发
useMemo重新计算图表数据,同时触发组件重渲染,图表就会加载最新索引对应的数据,完全不存在取值时机错误的问题
内容的提问来源于stack exchange,提问作者Shubham Singh
相关产品推荐
相关产品推荐

