MST
星途 面试题库

面试题:React基础:组件通信方式

在React中,父子组件、非父子组件之间分别有哪些常见的通信方式?请举例说明每种方式的实现思路。
36.3万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

父子组件通信

  1. 父传子
    • 实现思路:通过在父组件中向子组件传递属性(props)来实现通信。子组件通过接收这些props来获取父组件的数据。
    • 示例
import React from 'react';

// 子组件
const ChildComponent = ({ data }) => {
    return <div>{data}</div>;
};

// 父组件
const ParentComponent = () => {
    const parentData = '来自父组件的数据';
    return <ChildComponent data={parentData} />;
};

export default ParentComponent;
  1. 子传父
    • 实现思路:父组件将一个函数作为props传递给子组件,子组件调用该函数并将数据作为参数传递,从而实现将数据传递给父组件。
    • 示例
import React, { useState } from'react';

// 子组件
const ChildComponent = ({ handleChildData }) => {
    const childData = '来自子组件的数据';
    return <button onClick={() => handleChildData(childData)}>传递数据给父组件</button>;
};

// 父组件
const ParentComponent = () => {
    const [receivedData, setReceivedData] = useState('');
    const handleChildData = (data) => {
        setReceivedData(data);
    };
    return (
        <div>
            <ChildComponent handleChildData={handleChildData} />
            <p>接收到的数据: {receivedData}</p>
        </div>
    );
};

export default ParentComponent;

非父子组件通信

  1. 使用Context(上下文)
    • 实现思路:创建一个Context对象,通过Provider将数据传递给后代组件,无论组件嵌套多深,后代组件都可以通过Consumer或者useContext Hook来获取数据。
    • 示例
import React, { createContext, useState } from'react';

// 创建Context
const MyContext = createContext();

// 中间组件
const MiddleComponent = () => {
    return (
        <MyContext.Consumer>
            {value => <div>非父子组件获取到的数据: {value}</div>}
        </MyContext.Consumer>
    );
};

// 顶层父组件
const TopParentComponent = () => {
    const [sharedData, setSharedData] = useState('共享数据');
    return (
        <MyContext.Provider value={sharedData}>
            <MiddleComponent />
        </MyContext.Provider>
    );
};

export default TopParentComponent;
  1. 使用状态管理库(如Redux)
    • 实现思路:将应用的状态存储在一个单一的store中,各个组件通过dispatch action来更新store中的状态,同时可以订阅store的变化来更新自身。
    • 示例(简单示意,实际使用需更多配置)
// 安装redux及react - redux
// 定义action
const SET_DATA ='SET_DATA';
const setData = (data) => ({ type: SET_DATA, payload: data });

// 定义reducer
const initialState = { sharedData: '' };
const dataReducer = (state = initialState, action) => {
    switch (action.type) {
        case SET_DATA:
            return { ...state, sharedData: action.payload };
        default:
            return state;
    }
};

// 创建store
import { createStore } from'redux';
const store = createStore(dataReducer);

// 组件使用
import React from'react';
import { useSelector, useDispatch } from'react - redux';

const ComponentA = () => {
    const dispatch = useDispatch();
    return <button onClick={() => dispatch(setData('组件A设置的数据'))}>设置数据</button>;
};

const ComponentB = () => {
    const sharedData = useSelector(state => state.sharedData);
    return <div>组件B获取到的数据: {sharedData}</div>;
};
  1. 使用事件总线(自定义)
    • 实现思路:创建一个事件中心,各个组件在需要通信时向事件中心发布事件或者订阅事件。
    • 示例
// 创建事件总线
class EventBus {
    constructor() {
        this.events = {};
    }
    on(eventName, callback) {
        if (!this.events[eventName]) {
            this.events[eventName] = [];
        }
        this.events[eventName].push(callback);
    }
    emit(eventName, data) {
        if (this.events[eventName]) {
            this.events[eventName].forEach(callback => callback(data));
        }
    }
}

const eventBus = new EventBus();

// 组件A发布事件
const ComponentA = () => {
    const publishData = () => {
        eventBus.emit('custom - event', '来自组件A的数据');
    };
    return <button onClick={publishData}>发布事件</button>;
};

// 组件B订阅事件
const ComponentB = () => {
    React.useEffect(() => {
        const handleEvent = (data) => {
            console.log('组件B接收到的数据:', data);
        };
        eventBus.on('custom - event', handleEvent);
        return () => {
            eventBus.off('custom - event', handleEvent);
        };
    }, []);
    return <div>组件B等待接收数据</div>;
};