I would appreciate feedback on my approach:
BACKGROUND
- The application needs to have ReactJS components that will fetch data from server.
- The components will receive frequent updates from the server.
- There will be more than one component using the same data model.
- There will be different types of data model.
- It has to be easy to add new components just changing the data-model name.
- The application will probably be configurable.
APPROACH
Core:
I created a class called DataFetch that will fetch data from the server, which optionally can receive the Redux state options, SignalR options and callbacks using the methods onReceive() and onError().
When not configurated with Redux state options and SignalR options: the dataFetch will have the same axios functionality.When configurated with Redux state options: the DataFetch class will dynamically create a redux state according the state options and keep it updated using the result from request. The Redux state options are:stateNameandreducer. TheactionTypeswill be dynamically created using the stateName and for on success/error response of the request.When configurated with Signal options: the dataFetch receive real-time updates from server. if configurated: It will update the redux state and will call the callbacks (onSuccess, onError).
Adicional information:
- I'm using axios to fetch data from server.
- This state has been dynamically created using the official redux approach: ReducerManager.
- I'm using Core SignalR to add the real-time functionality to the application.
- I created a hook
useSignalRto easily use SignalR with React components. - All this is separated into their respective classes, functions to easily be tested.
How to use?
I created a hook called useDataFetch to easily use this functionality with `stateless React components.
The result from the hook will be a object like this: { data, error, isLoading }.
The syntax to use the hook is like this:
import React from 'react';
import { useSignalRContext } from './core/signalR';
import {
useDataFetch,
SignalRHubOptions,
ReduxStoreOptions
} from './core/dataFetch';
const ExampleComponent = props => {
const { dataModelId } = props;
const { someHubConnection } = useSignalRContext();
const signalRHubOptions = useMemo(
() =>
new SignalRHubOptions({
hubConnection: someHubConnection,
// Multiple components can be created for the same hubConnection.
// Therefore, we need to add a dataChangeMethodName by the component instance,
// otherwise, all instances of that component will receive the same message.
dataChangeMethodName: `DataChanged-${dataModelId}`
}),
[someHubConnection, dataModelId]
);
const reduxStoreOptions = useMemo(
() =>
new ReduxStoreOptions({
// Use diferrent stateName for different conponents.
stateName: `${dataModelId}_state`,
initialState: []
}),
[dataModelId]
);
// Receive data when:
// - perform the request with success;
// - signalR send a message;
// - redux state receive a update with the actionType SUCCESS;
// Receive error when:
// - perform the request with error;
// - redux state receive a update with the actionType FAILURE.
const { data, error, isLoading } = useDataFetch({
url: '/endpoint/${dataModelId}',
data: {
param1: 'value1'
},
signalRHubOptions: signalRHubOptions,
reduxStoreOptions: reduxStoreOptions
});
return {
/* render the component with the data or error or isLoading state */
};
};
export default ExampleComponent;