id | title | sidebar_label |
---|---|---|
api |
API |
API |
The createContainer
is a main function exported from the library,
which creates a provider and other hooks.
It takes one argument useValue
,
which is a hook that returns a tuple [state, update]
.
Typically, it's with useReducer and useState,
but it can be any custom hooks based on them.
Note: you can create multiple containers in one app.
import { createContainer } from 'react-tracked';
const useValue = (props) => useReducer(...);
const {
Provider,
useTracked,
useUpdate,
useTrackedState,
useSelector,
} = createContainer(useValue);
The Provider
returned by createContainer has to be put
in the parent component.
Typically, it's close to the root component,
but it can be (sometimes desirably) lower in the component tree.
const App = (props) => (
<Provider {...props}>
...
</Provider>
);
The useTracked
hook returned by createContainer is the recommended hook.
It simply returns the [state, update]
tuple that useValue
returns.
The state
is wrapped by Proxy for usage tracking.
const Component = () => {
const [state, dispatch] = useTracked();
// ...
};
The useUpdate
hook returned by createContainer is for update
from useValue
;
It's named "update" ambiguously, but typically
it would be renamed to "dispatch" for useReducer,
"setState" for useState, or "actions" for any actions.
const Component = () => {
const dispatch = useUpdate();
// ...
};
The useTrackedState
hook returned by createContainer is for state
from useValue
;
This is wrapped by Proxy as same as useTracked
.
Use this hook if you don't need update
.
This hook is compatible with reactive-react-redux.
const Component = () => {
const state = useTrackedState();
// ...
};
The useSelector
hook returned by createContainer is an optional hook.
Use this hook if state usage tracking doesn't work or fit well.
This hook is compatible with react-redux.
It would ease transition from/to react-redux apps.
const Component = () => {
const selected = useSelector(selector);
// ...
};
There is a tiny function exported from the library.
This is used to explicitly mark a prop object as used in a memoized component. Otherwise, usage tracking may not work correctly because a memoized component doesn't always render when a parent component renders.
import { trackMemo } from 'react-tracked';
const ChildComponent = React.memo(({ num1, str1, obj1, obj2 }) => {
trackMemo(obj1);
trackMemo(obj2);
// ...
});
There are some cases when we need to get an original object instead of a tracked object. Although it's not a recommended pattern, the library exports a function as an escape hatch.
import { getUntrackedObject } from 'react-tracked';
const Component = () => {
const state = useTrackedState();
const dispatch = useUpdate();
const onClick = () => {
// this leaks a proxy outside of render
dispatch({ type: 'FOO', value: state.foo });
// this works as expected
dispatch({ type: 'FOO', value: getUntrackedObject(state.foo) });
};
// ...
};