Home > Net >  Reactjs separation of UI and business logic
Reactjs separation of UI and business logic

Time:09-27

I am new to react and I find it sore in the eyes to look at the component flooded with lots of functions and variable initializations together with the UI. Is it possible to separate them?

Instead of the default setup, like below. How do I separate the business logic into another file?

function MyComponent() {
    const [data, setData] = useState('');
    const someFunc = () => {
        //do something.
    };
    ... some 100-liner initializations

   return ( 
       ...
   )
}

CodePudding user response:

Yes it is possible, That is called as Separation of concern.

You can create your component structure as below.

MyComponentDirectory
 - useCustomHook
 - Component
 - helper

The code will look like this one.

Hook

const useCustomHook = () => {

const [value, setValue] = useState('');
    const handleClick = (value) => {
        setValue(value)
        //do something.
    };
    ... some 100-liner initializations/business logic, states, api calls. 

return {
value, 
handleClick,
... // Other exports you need. 
} 
}

export default useCustomHook; 

Component

function MyComponent() {
    const {
     value, 
     handleClick, 
    ... // Other imports 
    } = useCustomHook() 

   return ( 
       <Element value={value} onClick={handleClick} />
   )
}

Helper

const doSomething = () => {}

EDIT

Here's a detailed example of React counter application using Separation of concern

Structure

Directory
- App
- Counter
- useCounter
- helper

App Component

import Counter from "./Counter";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <Counter />
    </div>
  );
}

Counter Component

import useCounter from "./useCounter";

const Counter = () => {
  const { count, increaseCount, decreaseCount } = useCounter();

  return (
    <div>
      <p>{count}</p>
      <div>
        <button onClick={increaseCount}>Increase</button>
        <button onClick={decreaseCount}>Decrease</button>
      </div>
    </div>
  );
};

export default Counter;

useCounter Hook

import { useState } from "react";
import numberWithCommas from "./helper";

const useCounter = () => {
  const [count, setCount] = useState(9999);

  const increaseCount = () => setCount(count   1);
  const decreaseCount = () => setCount(count - 1);

  return {
    count: numberWithCommas(count),
    increaseCount,
    decreaseCount
  };
};

export default useCounter;

Helper Function

const numberWithCommas = (x) => {
  return x.toString().replace(/\B(?=(\d{3}) (?!\d))/g, ",");
};

export default numberWithCommas;

Here's the working example in Codesandbox

Note: if you create a simple Javascript util function instead of hook then you won't be able to access other hooks, context inside that function.

CodePudding user response:

A common approach that I use myself is to separate the business logic into its own file myComponentHelper.js

This will also make it easier to test the function because it will not be able to use and change the react state without having it passed in as arguments and returning the changes.

myComponent/
  myComponent.jsx
  myComponentHelper.js
  myComponentTest.js
// myComponent.js

import { someFunc } from './myComponentHelper';

function MyComponent() {
    const [data, setData] = useState('');
    
    const x = someFunc(data);

    return ( 
        ...
    )
}
// myComponentHelper.js

export const someFunc = (data) => {
    //do something.
    return something;
}
// myComponentTest.js

import { someFunc } from './myComponentHelper';

test("someFunc - When data is this - Should return this", () => {
    const data = {...};
    const result = someFunc(data);
    expect(result).toEqual("correct business data");
});

CodePudding user response:

Separating business logic into other files can be done in various different ways.

  1. Create a helperFile.js that has logic or basically the functions required by the corresponding file.
  2. Creating Custom Hooks. More on that can be found here in the official docs or in this playlist (refer the videos at the very end)
  3. Global State mangement way - where contextAPI or Redux is used to seperate out state and business logic
  • Related