React stateless functional component with dynamic Redux state and SignalR

Viewed 252

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: stateName and reducer. The actionTypes will 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 useSignalR to 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;
0 Answers
Related