Link Search Menu Expand Document

Dependencies

Using a DependencyCreator function

The first call to useFPReducer takes an optional second argument that we’ll call dependencyCreator. dependencyCreator should have the following type (which is exported for package consumers):

interface DependencyCreator<A extends Action<any>, D> {
	(dispatch: Dispatch<A>): {dispatch: Dispatch<A>} & D;
}

where D is the type of a plain object that contains everything your handlers depend on beyond dispatch.


Example

Imagine a React component that needs to interact with two remote APIs to handle user payments: one to verify their account balance, and another to actually send the money. Our application defines an interface for working with each of these APIs, that look like this:

interface UserBankAccountService {
	approvePayment: (requestedAmount: number) => Promise<ApprovalInfo>
}

interface SecurePaymentService {
	sendPayment: (paymentData: PaymentData) => Promise<PaymentResponse>
}

Since these requests will be made sequentially (i.e., sendPayment depends on the result of approvePayment), it makes sense to define a single action handler that has access to them both. To get the dependencies into our handler, we’ll define a dependencyCreator function:

import {DependencyCreator} from 'react-use-fp'
import {MyActionTypes} from './path/to/actions'
import {BankServiceImplementation, PaymentServiceImplementation, UserBankAccountService, SecurePaymentService} from './services'

type Services = {
	BankService: UserBankAccountService;
	PaymentService: SecurePaymentService;
};

const createDependencies: DependencyCreator<MyActionTypes, Services> = (
	dispatch
) => ({
	dispatch,
	BankService: BankServiceImplementation,
	PaymentService: PaymentServiceImplementation,
});

Now, pass createDependencies to useFPReducer inside a component:

import React from 'react'
import {createDependencies, handlePaymentRequest} from './path/to/handler/stuff'
import {initialState, paymentReducer} from './path/to/state/stuff'

interface UserProfile {
	userID: string
}

const PaymentManager: React.FunctionComponent<UserProfile> = ({ userID }) => {
	// Note we can use other hooks for local state as well
	const [paymentAmount, setPaymentAmount] = React.useState(0);

	const [state, dispatch, actions] = useFPReducer(
		{
			INIT_PAYMENT: handlePaymentRequest,
		},
		createDependencies
	)(initialState, paymentReducer);

	const onSubmit = (e: any) => {
		e.preventDefault();
		dispatch(actions.INIT_PAYMENT(paymentAmount));
	};

	return (
		<main>
			<h1>So far you've sent: {state.alreadySent}</h1>
			<form onSubmit={onSubmit}>
				<input
					type="text"
					onChange={(e) => setPaymentAmount(e.target.value)}
				/>
				<button type="submit">Send Money!</button>
			</form>
		</main>
	);
};

And that’s it! Your handler will take care of the rest whenever the form is submitted.