You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过Context实现下拉菜单联动?变量未赋值问题排查

React Context下拉菜单联动问题排查与解决

问题根源分析

  1. Context作用域错误:原代码中TreatmentEditor的EditorContext.Provider仅包裹了自身的下拉组件,TitleEditor不在该Provider的覆盖范围内,导致TitleEditor获取的是Context默认值,调用setName无法修改TreatmentEditor的状态。
  2. 事件处理逻辑错误:
    • TitleEditor的handleChange硬编码传递固定值给父组件,且调用setName时传入对象,但TreatmentEditor的name初始为字符串,类型不匹配。
    • Kendo UI的DropDownList组件onChange事件的选中值存储在event.value中,而非event.target.value,原TreatmentEditor的取值方式错误。
  3. 状态管理分散:联动状态应该由共同父组件统一管理,而非在TreatmentEditor内部维护,否则无法实现跨组件状态同步。

正确实现方案

步骤1:重构Context与组件

将Context的状态提升到两个编辑器的共同父组件,确保两者共享同一状态上下文。修改editors.jsx如下:

import * as React from 'react';
import { DropDownList } from '@progress/kendo-react-dropdowns';
import { patients, treatments, rooms, therapists } from './data';

// 创建Context,定义统一的状态结构
const EditorContext = React.createContext({
  selectedTreatment: null,
  setSelectedTreatment: () => {},
});

export const TitleEditor = (props) => {
  const { setSelectedTreatment } = React.useContext(EditorContext);

  const handleChange = (event) => {
    // 触发父组件的回调,传递选中的患者ID
    props.onChange?.({ value: event.value.id });
    // 选中患者后,设置默认治疗项(可根据业务逻辑调整)
    setSelectedTreatment(treatments[0]);
  };

  return (
    <DropDownList
      onChange={handleChange}
      value={patients.find((p) => p.id === props.value)}
      data={patients}
      dataItemKey={'id'}
      textField={'name'}
    />
  );
};

export const TreatmentEditor = (props) => {
  const { selectedTreatment, setSelectedTreatment } = React.useContext(EditorContext);

  const handleChange = (event) => {
    // 更新Context中的治疗项状态
    setSelectedTreatment(event.value);
    // 触发父组件的回调,传递选中的治疗项值
    props.onChange?.({ value: event.value.value });
  };

  return (
    <DropDownList
      onChange={handleChange}
      // 优先使用Context中的选中值,无值时用默认项
      value={selectedTreatment || treatments.find(t => t.value === 138)}
      data={treatments}
      dataItemKey={'value'}
      textField={'text'}
    />
  );
};

// 导出Provider,供父组件使用
export const EditorProvider = EditorContext.Provider;

export const TherapistEditor = (props) => {
  const handleChange = (event) => {
    props.onChange?.({ value: event.value.value });
  };
  return (
    <DropDownList
      disabled={true}
      onChange={handleChange}
      value={therapists.find((t) => t.value === props.value)}
      data={therapists}
      dataItemKey={'value'}
      textField={'name'}
    />
  );
};

步骤2:父组件中使用Provider包裹

在包含两个编辑器的父组件(如App.jsx)中,通过EditorProvider传递状态,确保两个组件处于同一Context作用域:

import { useState } from 'react';
import { TitleEditor, TreatmentEditor, EditorProvider } from './editors';

function App() {
  // 父组件统一管理联动状态
  const [selectedTreatment, setSelectedTreatment] = useState(null);

  return (
    <EditorProvider value={{ selectedTreatment, setSelectedTreatment }}>
      <div style={{ padding: '20px' }}>
        <div style={{ marginBottom: '10px' }}>
          <label>患者:</label>
          <TitleEditor />
        </div>
        <div>
          <label>治疗项:</label>
          <TreatmentEditor />
        </div>
      </div>
    </EditorProvider>
  );
}

export default App;

关键修改说明

  • Context作用域修正:将Provider提升到父组件,让TitleEditor和TreatmentEditor共享同一状态上下文,确保状态修改能同步。
  • 状态类型统一:用selectedTreatment存储治疗项对象,避免字符串与对象的类型不匹配问题。
  • Kendo组件事件修正:使用event.value获取下拉组件的选中值,符合Kendo UI的API规范。
  • 回调逻辑优化:使用可选链操作符?.简化回调调用,避免空值报错。

内容的提问来源于stack exchange,提问作者Murray Johnson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 08:42:35