React/NextJS兄弟组件传值实现及回调函数报错修复
NextJS兄弟组件传值(表单到模态框)实现方案
问题背景
- 项目中
Formulario表单组件和Ambiente模态框组件为同级兄弟组件,需要将表单下拉框选中的值传递到模态框中展示 - 不希望使用Context方案,认为学习成本高且和现有项目结构不适配
- 自行尝试父组件回调传值时,触发
TypeError: props.parentCallback is not a function报错,多次调整未解决
报错核心原因
之前的代码存在3个关键问题:
- 父组件
App是函数式组件,错误混用了类组件的this.state、this.setState语法,函数组件不存在this实例,导致传入子组件的回调函数引用无效 Formulario组件中下拉框的onChange处理逻辑未正确绑定,也没有在选中值变化时调用父组件传入的回调- 父子组件传参时属性名不匹配:父组件状态中存储的字段是
message,传给模态框时却写的是this.state.data,无法取到正确值
完整修复代码
1. 父组件 App.js
将共享状态提升到父组件存储,分别给两个子组件传值和修改值的方法:
// app.js import React, { useState } from 'react'; import Formulario from '../components/formulario'; import Ambiente from '../components/ambiente'; const App = () => { // 用函数组件标准的useState管理两个组件共享的选中值 const [selectedOrg, setSelectedOrg] = useState(""); return ( <div> {/* 给表单组件传修改状态的回调方法 */} <Formulario onSelectChange={setSelectedOrg} /> {/* 给模态框组件传当前选中的状态值 */} <Ambiente selectedValue={selectedOrg} /> </div> ) } export default App;
2. 表单组件 Formulario.js
补全下拉选择的事件逻辑,选中变化时调用父组件回调把值传上去:
//components/formulario.js import React, { useState } from "react"; import { useForm } from "react-hook-form"; import axios from 'axios'; import { useRouter } from 'next/router'; // 接收父组件传入的回调 const Formulario = ({ onSelectChange }) => { // 补全之前缺失的register解构 const { register } = useForm(); const [seleccion, setSeleccion] = useState(""); const organizaciones = [ { label: "Seleccionar OSC", value: "test", }, ] // 下拉选择变化的处理函数 const handleSelect = (e) => { const currentVal = e.target.value; setSeleccion(currentVal); // 调用父组件回调,把当前选中值传递到父组件 onSelectChange(currentVal); } return ( <div className="selectContainer mx-auto p-5"> <div className="input-group input-group-dynamic mb-4"> <span className="input-group input-group-dynamic mb-4-addon"><i className="glyphicon glyphicon-list"></i></span> <select {...register('organizations', { required: true })} id="organizations" className="form-control selectpicker" value={seleccion} onChange={handleSelect} > {organizaciones.map((organizacion) => ( // 用唯一的value作为key,避免重名label导致的渲染问题 <option key={organizacion.value} value={organizacion.value}>{organizacion.label}</option> ))} </select> </div> </div> ) } export default Formulario;
3. 模态框组件 Ambiente.js
直接接收父组件传入的选中值渲染即可:
//components/ambiente.js import React from "react"; import Modal from "react-bootstrap/Modal"; import Button from 'react-bootstrap/Button'; // 接收父组件传入的选中值 const Ambiente = ({ selectedValue }) => { return ( {/* 有选中值时才显示模态框,可根据自己的业务逻辑调整显示规则 */} <Modal show={!!selectedValue}> <Modal.Header> <Modal.Title>Organizaciones</Modal.Title> </Modal.Header> <Modal.Body> <p>当前选中值:{selectedValue}</p> </Modal.Body> <Modal.Footer> <Button variant="secondary"> Cerrar </Button> </Modal.Footer> </Modal> ) } export default Ambiente;
方案说明
- 该方案为React标准的状态提升实现,不需要引入Context、状态管理库等额外依赖,完全适配现有项目结构,逻辑简单易维护
- 核心逻辑是:兄弟组件无法直接传值,就把两个组件需要共用的状态放到它们最近的共同父组件中维护,父组件负责把状态传给需要展示的子组件,把修改状态的方法传给负责输入的子组件
- 后续如果需要加模态框的打开/关闭控制,也可以用同样的方式把开关状态存在父组件即可
内容的提问来源于stack exchange,提问作者HomerO
相关产品推荐
相关产品推荐

