A closure is the combination of a function bundled together (enclosed) with references to its surrounding state (the lexical environment). https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures#lexical_scoping
By closure we can use variable value even though the variable is in outside of lexical scope. Lexical scope is that the way of parser understand the variable.
For example, let me show the useState imitation.
function useState(initialValue) {
var _val = initialValue
function state() {
return _val
}
function setState(newVal) {
_val = newVal
}
return [state, setState]
}
var [foo, setFoo] = useState(0)
console.log(foo()) // 0
setFoo(1)
console.log(foo()) // 1
reference : https://hewonjeong.github.io/deep-dive-how-do-react-hooks-really-work-ko/
When we call setFoo(1), _val is in outside of lexicalcope. However, we can access to the _val and change it. In this way we can manage the state in the react.
We can use this hook for making isolated state from main logic and modify it and use it. I will show the example in the next blog.
Custom hook have useXXX as prefix. This prefix let react app knows that the function is custom hook. It has some grammer that we should follow. One of main grammers is that custom hook should be called in component level. But we can use custom hook in the custom hook. So i made a custom hook for api handling.
import { useCallback } from "react"
import axios from "axios"
import { urlTypes } from "./configs/urlTypes";
import { urls } from "./configs/urls";
import { useDispatch } from 'react-redux'
import { showAlertModal } from "@/modules/alertModalReducer";
import service from '@/modules/Common/service'
import { useCookies } from "react-cookie";
interface configsInterface {
method: string
params?: any
headers?: {
Authorization: string
}
}
const useApiHandling = <T = any>({
urlType,
method = 'get',
needAuthority = true
}: {
urlType: urlTypes,
method?: string,
needAuthority?: boolean,
}) => {
const [cookies, ,] = useCookies(["loginToken", "loginStatus", "companySeq"]);
const dispatch = useDispatch()
const getConfigs = useCallback((params: any = {}) => {
const configs: configsInterface = {
method,
params,
}
if (needAuthority) {
const { loginToken } = cookies
configs["headers"] = { Authorization: `Bearer ${loginToken}` }
}
return configs
}, [method, needAuthority, cookies])
const checkValid = (result: any) => {
const validChecker = result?.data?.result
if (typeof validChecker === "boolean" && validChecker === false) {
const message = service.getValue(result, "data.message", "error message")
dispatch(showAlertModal(message, "", "확인"));
return false
}
return true
}
const doRequest = useCallback(async (params: any = {}) => {
try {
const url = urls[urlType]
if (url) {
const fetchUrl = process.env.REACT_APP_API_HOST + url
const configs = getConfigs(params)
const result = await axios(fetchUrl, configs)
const isValid = checkValid(result)
if (!isValid) {
return null
} else {
return result
}
}
return null
}
catch (error) {
dispatch(showAlertModal('error', '', 'confirm'));
return null
}
}, [urlType, method]);
return { doRequest }
};
export default useApiHandling
By this hook i can reduce the code when i use restfull api. First of all i can reduce error handling cod. I used the try, catch when i call axios and i make a error modal when there is a error. Also it shows error message, if the server sends error message.
Second I can reduce config code, like cookie or params. It is annoying that always call cookie and put in the header when we use api. I reduced it by this hook.
Third I can reduce handling of api endpoint code. I can get the endpoint url string by the url type. When i want to call the api, i just use the type, not write down a string. See the below code.
const { doRequest: getEvaluationYearData } = useApiHandling({ urlType: urlTypes.GET_EVALUATION_YEAR_DATA_LIST })
Actually this api handling hook can be used in just a simple function but we can not use useCookie in the simple function.
So i made a customfunction for using useCookie.
I will show the other example of custom hook in the next blog.