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 (
...
)
}
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.