Using the Producer
Roact Reflex provides useful hooks similar to React Redux that allow you to access the root producer, its state, and to dispatch actions.
- 📂 How to set up Roact Reflex in your app
- ⚡️ How to dispatch actions
- 📦 How to use a typed
useProducer
hook
Setting up Roact Reflex
To use Roact Reflex, you must first pass your root producer to the <ReflexProvider>
component. By doing this, you enable Reflex Hooks for your Roact app.
You can render the <ReflexProvider>
component anywhere in your app, but it must be rendered above any components that use the Hooks. We recommend putting it at the top-level of your app, wrapping your root components.
Roact.mount(
<ReflexProvider producer={producer}>
<App />
</ReflexProvider>,
playerGui,
);
Dispatching actions
The useProducer
hook lets you access the producer and dispatch actions to the root producer. You can use this hook to dispatch actions from any component that is wrapped in a <ReflexProvider>
.
Say our root producer has a todos
slice that contains actions to add a todo:
import { createProducer } from "@rbxts/reflex";
interface TodosState {
readonly list: readonly string[];
}
const initialState: TodosState = {
list: [],
};
export const todosSlice = createProducer(initialState, {
addTodo: (state, todo: string) => ({
...state,
list: [...state.list, todo],
}),
});
We can use the useProducer
hook to dispatch the addTodo
action from a component:
import Roact from "@rbxts/roact";
import { useProducer } from "@rbxts/roact-reflex";
import { RootProducer } from "./producer";
function Button() {
const producer = useProducer<RootProducer>();
return (
<textbutton
Text="Add Todo"
Size={new UDim2(0, 100, 0, 50)}
Event={{
Activated: () => producer.addTodo("Hello, world!"),
}}
/>
);
}
You can also destructure the useProducer
hook to get the addTodo
action directly:
function Button() {
const { addTodo } = useProducer<RootProducer>();
// ...
Typed useProducer
hook
If you want to use the useProducer
hook without passing the type of your root producer, you can use the UseProducerHook
type to create a typed hook:
import { UseProducerHook, useProducer } from "@rbxts/roact-reflex";
import { RootProducer } from "./producer";
export const useRootProducer: UseProducerHook<RootProducer> = useProducer;
Why use a hook instead of importing the producer?
You may be wondering why we use a hook to access the producer instead of just importing it directly. Some good reasons to use a hook are:
- It makes your components more reusable
- It allows you more flexibility in testing
- Your components are easier to test in isolation
If you use a ReflexProvider
to pass the root producer, you can create a mock producer and pass it to your components in tests. Your components can be easier to isolate and run tests on.
Using a hook also makes your components more reusable. If you import the producer directly, you might need to refactor your component when moving it to a different app that has a different producer set up.
Subscribing to state
To learn how to subscribe to state, we'll learn about the useSelector
hook on the next page.
Summary
- Make sure to pass your root producer to the
<ReflexProvider>
component - You can use the
useProducer
hook to access the root producer and dispatch actions - Using a hook to access the producer makes your components more reusable and easier to test