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

React如何将子组件Selector的选中对象状态传递给父组件

实现方案

React中子组件向父组件传递数据的标准逻辑是:父组件提前将接收数据的回调函数通过props传给子组件,子组件内部数据更新时触发该回调,将需要传递的数据作为参数回传给父组件。

步骤1:修改父组件(index.js)

  1. 新增state存储选中的成员ID列表、群组名称
  2. 给子组件Selector传入接收选中数据的回调函数
  3. 将群组成员输入框的value绑定为state中的选中成员列表
    修改后完整代码:
import React from "react";
import ReactDOM from "react-dom";
import { TextField, Button } from "@material-ui/core";
import Selector from "./Selector";

function App() {
  // 新增state存储选中的成员ID、群组名称
  const [selectedMembers, setSelectedMembers] = React.useState([]);
  const [groupName, setGroupName] = React.useState("");

  const createAction = () => {
    // 提交时直接取groupName和selectedMembers即可
    console.log("提交参数:", {
      groupName,
      members: selectedMembers
    });
    console.log("fire up post request");
  };

  return (
    <div>
      <div>
        <h1>Create group (parent)</h1>
        <form>
          <TextField
            id="name"
            label="Group name"
            variant="outlined"
            required={true}
            value={groupName}
            onChange={(e) => setGroupName(e.target.value)}
          />
          <br />
          <br />
          <p>如何将选中值传递到此处:</p>
          <TextField
            id="members"
            label="Group members"
            variant="outlined"
            required={true}
            inputProps={{ readOnly: true }}
            fullWidth
            // 绑定选中的成员ID,用逗号分隔和子组件展示效果一致
            value={selectedMembers.join(",")}
          />
        </form>
        <br />
        <Button variant="contained" color="primary" onClick={createAction}>
          Create group
        </Button>
      </div>
      <br />
      <br />
      {/* 给子组件传入接收数据的回调函数 */}
      <Selector onChange={setSelectedMembers} />
    </div>
  );
}

ReactDOM.render(<App />, document.querySelector("#app"));

步骤2:修改子组件(Selector.js)

  1. 删除无效代码行props = selectionObj
  2. 新增useEffect监听内部选中状态变化,每次变化就调用父组件传入的回调,将最新选中ID列表回传
  3. 功能验证完成后可删除子组件底部展示选中ID的TextField
    修改后完整代码:
import React from "react";
import {
  Box,
  Typography,
  Checkbox,
  TextField,
  Button
} from "@material-ui/core";

const DATA = [
  { id: "1", name: "First name" },
  { id: "2", name: "Second name" },
  { id: "3", name: "Third name" },
  { id: "5", name: "Fourth name" },
  { id: "6", name: "Fifth name" }
];

export default function Selector(props) {
  const [selectionObj, setSelectionObj] = React.useState({});

  // 监听selectionObj变化,触发父组件传入的回调回传数据
  React.useEffect(() => {
    props.onChange(Object.keys(selectionObj))
  }, [selectionObj, props])

  const onOptionSelect = (option) => (e) => {
    if (selectionObj[option.id]) {
      let duplicateSelectedObj = { ...selectionObj };
      delete duplicateSelectedObj[option.id];
      setSelectionObj(duplicateSelectedObj);
    } else
      setSelectionObj((prev) => ({ ...prev, ...{ [option.id]: option.name } }));
  };

  const isAllChecked = DATA.length === Object.keys(selectionObj).length;

  const onCheckAllClick = () => {
    if (isAllChecked) {
      setSelectionObj({});
    } else {
      let allSelected = {};
      DATA.forEach((data) => {
        allSelected[data.id] = data.name;
      });
      setSelectionObj(allSelected);
    }
  };

  return (
    <Box>
      <Typography variant="h5">Selector (child component)</Typography>
      <Box my={2}>
        {/* Table Header. */}
        <Box display="flex" alignItems="center" borderBottom={1}>
          <Box display="flex" flex={1}>
            <Checkbox
              checked={isAllChecked}
              indeterminate={
                Object.keys(selectionObj).length > 0 && !isAllChecked
              }
              onChange={onCheckAllClick}
            />
          </Box>
          <Box display="flex" flex={10}>
            <Typography variant="h6">Id</Typography>
          </Box>
          <Box display="flex" flex={10}>
            <Typography variant="h6">Name</Typography>
          </Box>
        </Box>
        {/* Table contents */}
        {DATA.map((data) => (
          <Box key={data.id} display="flex" alignItems="center">
            <Box display="flex" flex={1}>
              <Checkbox
                onChange={onOptionSelect(data)}
                checked={Boolean(selectionObj[data.id])}
              />
            </Box>
            <Box display="flex" flex={10}>
              <Typography variant="h6">{data.id}</Typography>
            </Box>
            <Box display="flex" flex={10}>
              <Typography variant="h6">{data.name}</Typography>
            </Box>
          </Box>
        ))}
      </Box>
      <Button
        variant="contained"
        color="primary"
        onClick={() => console.log("Selected ids: ", Object.keys(selectionObj))}
      >
        Get Payload
      </Button>
      <br />
      <br />
      {/* 验证完成后可删除下方这个TextField */}
      <TextField
        value={Object.keys(selectionObj)}
        variant="outlined"
        inputProps={{ readOnly: true }}
        fullWidth
      />
    </Box>
  );
}

修改完成后,子组件每次勾选、取消勾选、全选/反选操作,都会同步将选中的用户ID列表回传给父组件,父组件的群组成员输入框会自动同步展示内容,提交表单时直接使用父组件内存储的groupName和selectedMembers即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 19:45:06