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.