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

React中克隆传入组件的props数据遇只读属性赋值错误求助

问题分析与解决方法

错误根源

你遇到的Cannot assign to read only property 'selectedData' of object错误,核心原因是React的props是只读的,绝对不能直接修改props的属性值(比如props.selectedData = data这种操作)。此外你的数据流逻辑也有问题:父组件的clonedData是普通变量,无法追踪更新,子组件的修改也无法同步回父组件。


分步解决方案

1. 修改父组件(App.js):将普通变量改为React状态

把父组件中的clonedData改成React状态,同时添加回调函数接收子组件的选中数据,实现双向数据同步:

import React, { useState } from 'react';
import MultiDropdown from './Components/MultiDropdown/MultiDropdown.component';
import { allOptions } from './Utils/DummyData';
import "./App.css";

const App = () => {
  // 将普通变量转为React状态,用于追踪更新
  const [clonedData, setClonedData] = useState([
    { value: 'Normal😐', label: 'Normal😐' },
    { value: 'Angry😡', label: 'Angry😡' },
    { value: 'Love😍', label: 'Love😍' },
  ]);

  // 定义回调,接收子组件传来的选中值并更新父状态
  const handleSelectedUpdate = (selectedValues) => {
    // 把选中的value映射为和初始结构一致的对象数组
    const updatedData = selectedValues.map(value => ({
      value,
      label: value
    }));
    setClonedData(updatedData);
  };

  return(
    <div className='app'>
      <MultiDropdown 
        data={allOptions} 
        placeholder="Select Options"
        selectedData={clonedData}
        onSelectedUpdate={handleSelectedUpdate} {/* 传递回调给子组件 */}
      />
      <button onClick={() => console.log("Selected", clonedData)}>Click to See SelectedData</button>
    </div>
  )
}

export default App;

2. 修改子组件(MultiDropdown.tsx):移除props修改逻辑,通过回调同步数据

去掉直接修改props的代码,改用父组件传递的回调函数同步选中状态,同时监听父组件的selectedData变化以同步子组件内部状态:

import React, { useEffect, useState } from 'react';

// 明确Props类型,包含回调函数
type Props = {
  data: any[];
  placeholder: string;
  selectedData: { value: string; label: string }[];
  onSelectedUpdate: (selectedValues: string[]) => void;
};

export default function MultiDropdown(props: Props): React.ReactNode {
  // 从父组件props初始化子组件内部状态
  const [selectedValues, setSelectedValues] = useState(
    props.selectedData.map(opt => opt.value)
  );

  // 监听父组件selectedData变化,同步子组件状态
  useEffect(() => {
    setSelectedValues(props.selectedData.map(opt => opt.value));
  }, [props.selectedData]);

  // 处理下拉框选择变化,同时调用父组件回调同步数据
  const handleDropdownChange = (selected: any[]) => {
    const values = selected.map(opt => opt.value);
    setSelectedValues(values);
    // 把选中值传给父组件更新状态
    props.onSelectedUpdate(values);
  };

  return (
    <div>
      <Select
        {...DropDownProps(props, selectedValues, SelectOption)}
        onChange={handleDropdownChange}
      />
      {selectedValues.map(opt => (
        <ListContainer 
          key={opt} 
          opt={opt} 
          data={selectedValues} 
          set={setSelectedValues} 
        />
      ))}
    </div>
  );
}

关键修改点说明

  • 移除了子组件中props.selectedData = data的错误代码,严格遵循React props只读原则
  • 父组件通过useState管理选中数据,确保状态变化能触发组件重渲染
  • 子组件通过回调函数onSelectedUpdate将选中数据传递回父组件,实现双向数据同步
  • 去掉了子组件中错误的ref={props.selectedData}配置(ref不能绑定普通数组)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.03 13:30:51