useEffect(() => {
})
useEffect(() => {
}, [])
useEffect(()=>{
}, [value])
불변성을 유지하기 위해 많이 쓰는 훅이다.
const [text, setText] = useState();
useEffect(() => {
setText("useState!!!")
}, [text])
이런방식으로 많이 쓰이고 불러온 데이터들을 가공해야 할 경우 데이터를 useState안에 담아서 새로 가공을 해서 쓰는 경우도 있다.
const text = useMemo(() =>
function(), [])
첫번째 파라미터에는 어떤연산을 할지 정의하는 함수를 넣어주고 두번째에는 deps배열을 넣어주면 된다. 위의 배열안에 넣은 값이 바뀔때만 등록한 함수를 호출해서 값을 연산하고 값이 바뀌지 않을경우에는const Remove = useCallback(id => {
setUsers(users.filter(user => user.id !==id));
}, [users]);
함수 안에서 사용하는 상태 혹은 props가 있을경우 usecallback은 deps배열안에 무조건 포함을 시켜야한다. useCallback의 경우는 바로 최적화를 한다기 보다는 컴포넌트 렌더링 최적화를 같이 해야만 function reducer(state, action){
생략
}
function Counter(){
const [number, dispatch] = useReducer(reducer, 0);
return(~~~)
}
이런식으로 counter컴포넌트안에서 쓸 값들을 밖에서 action을 정의하고 쓸수 있는 것이다.리덕스의 미들웨어로 비동기작업을 처리할때 많이 사용하며 액션객체가 아닌 함수를 디스패치해서 쓸 수 있다. redux에서 thunk함수를 쓸려면
먼저 redux-thunK 패키지를 설치하고 applyMiddlewares에 적용을 해야한다 그리고 기존의 액션타입을 생성하고 짜는 redux구조로 코드를 구현해보면
const INCREASE = 'INCREASE';
export const increase = () => ({ type: INCREASE});
export const increaseAsync = () => dispatch => {
setTimeout(() => dispatch(increase()), 1000);
};
export default function couter(state = initailState, action) {
//reducer정의
}
이런식으로 thunk 함수를 정의하고
import {increaseAsync} from "경로";
const Increase = () => {
dispatch(increaseAsync());
}
와 같이 컴포넌트에서 바로 함수를 불러서 디스패치를 할 수 있게된다.
ReduxToolkit createAsyncThunk + createSlice + extraReducer
이번 프로젝트에서 리덕스 스토어에 상태를 업데이트 할때 쓰던 조합이다.
export const getAllBeer = createAsyncThunk(
"beer/getAllBeer",
async (data, thunkAPI) => {
const response = await axiosInstance.get(`/api/beer/list/${data}`);
return response.data;
}
);
이렇게 thunk를 써서 함수를 바로 디스패치 한다음 서버에 데이터 요청을 하고 받은 response.data를 action.payload의 변수안에 보낸다
export const beerSlice = createSlice({
name: "beer",
initialState,
extraReducers: (builder) =>
builder
.addCase(getAllBeer.fulfilled, (state, action) => {
state.beerList = action.payload;
})
.addMatcher(
(action) => {
return action.type.includes("/pending");
},
(state, action) => {
state.isLoading = true;
state.isDone = false;
state.isError = null;
}
)
.addMatcher(
(action) => {
return action.type.includes("/fulfilled");
},
(state, action) => {
state.isLoading = false;
state.isDone = true;
}
)
.addMatcher(
(action) => {
return action.type.includes("/rejected");
},
(state, action) => {
state.isLoading = false;
state.isError = action.error;
console.log(action.error);
}
),
});
여기서 상태반영을 하고 pending, fulfilled, rejected의 상태를 통합으로 관리해줬다. 에러가 발생할 경우 에러를 띄우고 fullfilled되면 state.isDone을 true로 바꾸는 방식으로 통합해서 관리해줬다.
그리고 컴포넌트단에서는 원래 thunk함수를 쓰듯이 함수를 import해와서 바로 디스패치를 해서 사용하면 된다.
마찬가지로 상태관리를 위한 라이브러리로 reduxjs/toolkit에서는 reselect를 별도의 설치없이 바로 사용할수 있다.
const beer = useSelector((state) => state.beer.beerList)
기존의 useSelector는 이런 식으로 스토어의 데이터를 컴포넌트에서 핸들링해서 사용할 수 있으나 컴포넌트가 리렌더링 될때마다 함수가 재실행되는 낭비가 있다
그래서 reselect를 이용하게 되면 reduxd store값을 가져와서 계산을 해서 redux가 적은양의 데이터만 가지고 있게 도와준다. 그리고 메모이징되기 때문에 재계산 방지에 효율적이다.
const beer_One = (state) => state.beer.beerOne;
export const oneBeer = createSelector(beer_One, beer_One => {
return beer_One;
}); // 맥주 1개데이터
기본적인 예시이고 state에서 필요한 부분을 가져오는 역할을 하고 그 다음 인자인 함수에서는 inputSelectors에서 반환된 값을 인자로 받아서 수행을 하는데 inputSelector의 값이 바뀌지 않을경우는
저장된 cache값을 사용하여 불필요한 재계산을 하지 않도록 도와준다.