Refs
Purpose
Unlike frameworks like React DOM or vanilla JavaScript, the is no way to modify the DOM elements in Mini Program. But there is still some cases that developers need to access the instance of a specific element. For example, wx.createIntersectionObserver API return an observe that could watch the page scrolling and trigger when the intersection of a target element changed.
Refs
Because GojiJS use React components rather than Mini Program custom components, an elements might be rendered in the top of page or inside a custom component according to different runtime.
For example, this case on WeChat the view-a
rendered in the page and the view-b
rendered inside
Subtree
component.
Subtree
is a special built-in component that tell GojiJS to render its children in another custom component. It works likeFragment
on non-WeChat platforms.
const Comp = () => {
const refA = useRef<GojiPublicInstance | null>();
const refB = useRef<GojiPublicInstance | null>();
return (
<View className="view-a" ref={refA}>
<Subtree>
<View className="view-b" ref={refB}>
hi
</View>
</Subtree>
</View>
);
};
render(<Comp />);
So we should use refA
to observe the view-a
and refB
to view-b
.
useRenderedEffect
There is a main difference between Mini Programs and Web Apps, it is all DOMs modifications are async applied. The second argument of setData is a callback that run every time DOMs changes done.
useRenderedEffect
works as same as the setData
's callback. This hook runs after it make sure the
DOMs are ready to observe. It's the earliest time to access the refs. If you use refs inside
useEffect
, the ref.current
might be undefined
.
Please remember we recommend to use useEffect
in any time only except using refs.
Usage
Here is a full example.
getComponentInstance
returns the this
instance of which custom component that rendered inside.
getComponentInstance
returns undefined
if the element was rendered on page.
import React, { useRef } from 'react';
import { View, useRenderedEffect, GojiPublicInstance } from '@goji/core';
const Comp = () => {
const viewRef = useRef<GojiPublicInstance | null>();
useRenderedEffect(() => {
const init = async () => {
if (viewRef.current) {
const componentInstance = await viewRef.current.getComponentInstance();
const observe = componentInstance
? componentInstance.createIntersectionObserver()
: wx.createIntersectionObserver();
observer.relativeToViewport(...);
}
};
init();
}, []);
return <View ref={viewRef}>hello, world!</View>;
};