Frontend Development 7 min read

Using @vue/reactivity in React: Custom Hooks and HOC for Reactive State

This article demonstrates how to leverage the @vue/reactivity package inside React by creating a custom useReactive hook for function components and a reactiveHoc higher‑order component for class components, explaining the underlying concepts, implementation steps, and practical usage with full code examples.

ByteFE
ByteFE
ByteFE
Using @vue/reactivity in React: Custom Hooks and HOC for Reactive State

Preface

Since Vue 3.0 was released, its core reactivity system has been extracted into the @vue/reactivity package, allowing developers to use Vue's reactivity outside the Vue framework. The author explores using @vue/reactivity in React to build reactive state without repeatedly calling this.setState or useState .

To make the solution reusable, a custom hook useReactive is written for function components and a higher‑order component reactiveHoc for class components.

Function Component – Custom Hook useReactive

Implementation

import { reactive, effect } from '@vue/reactivity'
import React, { useRef, useEffect, useMemo, useState } from 'react'
function useReactive(initState) {
  const reactiveState = useRef(initState) // state
  const [, forceUpdate] = useState(0)
  const state = useMemo(() => reactive(reactiveState.current), [reactiveState.current])
  useEffect(() => {
    let isdep = false
    effect(() => {
      for (let i in state) { state[i] } // dependency collection
      isdep && forceUpdate(num => num + 1) // force update
      if (!isdep) isdep = true
    })
  }, [state])
  return state
}

Idea

Use useRef to store the raw object so the reference stays stable across renders.

Wrap the object with reactive inside useMemo to rebuild only when the ref changes.

Use useEffect to run effect for dependency collection, guarded by a flag to avoid an extra update on the first run.

Use a dummy useState to trigger a forced re‑render when the reactive effect fires.

Usage

function Index() {
  const state = useReactive({ number: 1, name: 'alien' })
  return (
你的姓名是: { state.name }
{ new Array(state.number).fill(0).map(() => '👽') }
state.number++}>👽++
state.number--}>👽--
state.name = e.target.value} />
)
}

Class Component – Reverse‑Inheritance HOC reactiveHoc

For class components, manually injecting reactive and effect is cumbersome. A higher‑order component that extends the original component can automatically make its state reactive.

Implementation

import { reactive, effect } from '@vue/reactivity'
import React from 'react'
function reactiveHoc(Component) {
  const originalDidMount = Component.prototype.componentDidMount
  return class WrapComponent extends Component {
    constructor(props) {
      super(props)
      this.state = reactive(this.state)
    }
    __isFirst = false
    componentDidMount() {
      effect(() => {
        for (let i in this.state) { this.state[i] } // make reactive
        this.__isFirst && this.forceUpdate()
        !this.__isFirst && (this.__isFirst = true)
      })
      originalDidMount && originalDidMount.call(this)
    }
  }
}

Idea

Reverse inheritance lets the HOC access the inner component’s state directly.

The HOC hijacks componentDidMount to set up an effect that tracks state changes and forces an update after the first render.

Usage

@reactiveHoc
class Index extends React.Component {
  constructor(props) {
    super(props)
    this.state = { number: 0, name: 'alien' }
  }
  componentDidMount() {
    console.log(6666)
  }
  render() {
    const { state } = this
    return (
你的姓名是: { state.name }
{ new Array(state.number).fill(0).map(() => '👽') }
state.number++}>👽++
state.number--}>👽--
state.name = e.target.value} />
)
  }
}

Conclusion

The purpose of this article is not to promote using @vue/reactivity in production React projects, but to illustrate how to combine Vue’s reactivity with React’s component model, and to teach the creation of custom hooks and higher‑order components for a more advanced React stack.

VueCustom HooksReactivityHigher-Order Component
ByteFE
Written by

ByteFE

Cutting‑edge tech, article sharing, and practical insights from the ByteDance frontend team.

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.