Frontend Development 13 min read

Component Communication in React 18 and Vue 3: Parent‑Child, Sibling, and Cross‑Level Patterns

This article compares React 18 and Vue 3 component communication techniques—including parent‑child, sibling, and cross‑level patterns—provides detailed code examples for props, emit, context, provide/inject, and summarizes their respective advantages and use cases in modern web development.

Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Rare Earth Juejin Tech Community
Component Communication in React 18 and Vue 3: Parent‑Child, Sibling, and Cross‑Level Patterns

Introduction

After exploring Vue 3, the author initiates a comparison with React 18 focusing on component communication methods: parent‑child, sibling, and cross‑layer communication.

1. Parent‑Child Communication

React 18

Data is passed from parent to child via props attributes, and the child accesses them through the props object. The reverse direction uses a callback function passed as a prop, which the child invokes to send data back.

function App() {
    return (
);
}
function Son1(props) {
    return (
姓名:{props.name}
年龄:{props.age}
内容:{props.children}
);
}

The special props.children prop contains any nested content inside the component tag.

import React, { useState } from 'react';
function Parent() {
    const [msg, setMsg] = useState('');
    const handleMsg = (msg) => { setMsg(msg); };
    return (
父组件状态:{msg}
);
}
function Son1({ handleMsg }) {
    const sonMsg = '我是Son1子组件';
    return
handleMsg(sonMsg)}>点击传递消息
;
}

Vue 3

Parent components pass data via props , while child components declare received props using defineProps . Methods can be exposed to the parent with defineExpose and accessed via ref or template refs.

<template>
  <Son :name="parentName" :age="parentAge" />
</template>
<script setup>
import { ref } from 'vue';
import Son from './Son.vue';
const parentName = ref('李四');
const parentAge = ref(20);
</script>
// Son.vue
<script setup>
defineProps({
  name: { type: String, required: true },
  age: Number
});
</script>
// Expose method
<script setup>
import { defineExpose } from 'vue';
defineExpose({
  foo() { console.log('这是来自子组件的foo方法'); },
  childName: '这是子组件的属性'
});
</script>
// Parent uses ref
<template>
  <Child ref="cmp" />
  <button @click="handleClick">按钮</button>
</template>
<script setup>
import { ref } from 'vue';
import Child from './Child.vue';
const cmp = ref(null);
function handleClick() {
  cmp.value.foo();
  cmp.value.childName = '修改了子组件的属性';
  console.log(cmp.value);
}
</script>

2. Cross‑Layer Communication

React

Implemented with the Context API: create a context, wrap components with a Provider , and consume the value using the useContext hook.

import React, { createContext, useContext } from 'react';
const MsgContext = createContext();
function ContextApp() {
  const msg = 'this is app';
  return (
我是 App 组件
);
}
function A() {
  const sonMsg = '我是 son1 子组件';
  return (<>{sonMsg}
);
}
function B() {
  const msg = useContext(MsgContext);
  return
this is B,{msg}
;
}
export default ContextApp;

Vue 3

Uses provide in the ancestor and inject in descendants.

<!-- Parent.vue -->
<template>
  <div>
    <h2>我是 App 组件</h2>
    <A />
  </div>
</template>
<script setup>
import { provide } from 'vue';
import A from './A.vue';
const msg = 'this is app';
provide('msg', msg);
</script>
<!-- B.vue -->
<template>
  <div>this is B,{{ msg }}</div>
</template>
<script setup>
import { inject } from 'vue';
const msg = inject('msg');
</script>

3. Sibling Communication

React

Achieved by lifting shared state to a common parent and passing callbacks via props.

function Parent() {
  const [msg, setMsg] = useState('');
  const getMsg = (msg) => setMsg(msg);
  return (
父组件状态:{msg}
);
}
function Son1({ getMsg }) {
  const sonMsg = '我是Son1子组件';
  return
getMsg(sonMsg)}>传递消息
;
}
function Son2({ msg }) {
  return
兄弟组件接收到的消息:{msg}
;
}

Vue 3

Similarly, the parent passes data via props and children emit events back.

<!-- Parent.vue -->
<template>
  <Son1 @sendMessage="receiveMessage" />
  <Son2 :msg="message" />
</template>
<script setup>
import { ref } from 'vue';
import Son1 from './Son1.vue';
import Son2 from './Son2.vue';
const message = ref('');
function receiveMessage(msg) { message.value = msg; }
</script>
<!-- Son1.vue -->
<template>
  <button @click="sendMessage">传递消息</button>
</template>
<script setup>
const emit = defineEmits();
function sendMessage() { emit('sendMessage', '我是Son1子组件'); }
</script>
<!-- Son2.vue -->
<template>
  <h2>兄弟组件接收到的消息:{{ msg }}</h2>
</template>
<script setup>
defineProps({ msg: String, required: true });
</script>

Comparison Table

Feature

React

Vue 3

Cross‑layer method

context

&

useContext
provide

&

inject

Data flow direction

Provider

passes down,

Consumer

reads

provide

in parent,

inject

in descendant

Typical scenario

Medium‑scale apps needing global state

Deeply nested component data sharing

Conclusion

Both React 18 and Vue 3 offer mechanisms to simplify component communication. React relies on the Context API for cross‑layer sharing, while Vue 3 uses provide / inject . Understanding these patterns helps developers choose the appropriate approach for their project's architecture.

frontendJavaScriptReactVuecomponent communicationprovide/injectContext API
Rare Earth Juejin Tech Community
Written by

Rare Earth Juejin Tech Community

Juejin, a tech community that helps developers grow.

0 followers
Reader feedback

How this landed with the community

login Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.