๐คทโ๏ธ ๋ณธ๋ก ์ ์์
react-query๋ React์์ ๋ง์ด ์ฌ์ฉ๋๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ฉฐ ๋ค์ํ ํ ๊ณผ ์ ํธ๋ฆฌํฐ๋ฅผ ์ ๊ณตํด ์ฃผ๋ฉฐ ๊ฐ๋ฐ์์ ํธ๋ฆฌ์ฑ๊ณผ ์์ฐ์ฑ์ ๋์ฌ์ค๋๋ค.
๋ณธ๋ก ์ ์์ ์๋์ ๊ธ๋ค์ ์ฝ๊ณ ์ค์๋ ๊ฒ์ ์ถ์ฒ๋๋ฆฝ๋๋ค.
useMutation๋ํ ๊ธ์ ์ดํดํ๋๋ฐ ๋ง์ ๋์์ด ๋ฉ๋๋ค.
react-query ์ฌ์ฉ๋ฒ์ ๋ํด ์์๋ณด๊ธฐ
https://cometruedream.tistory.com/130
React-query ์ํ ๊ด๋ฆฌ
๐React-query ์๊ธฐ์ ์ JSX๋?JSX(javascript XML)๋ javascript์ XML์ ์ถ๊ฐํ ํ์ฅํ ๋ฌธ๋ฒ์ด๋ค.JSX๋ React์์ ์ฌ์ฉ๋๋๋ฐ ๊ณต์์ ์ธ ์๋ฐ์คํฌ๋ฆฝํธ ๋ฌธ๋ฒ์ ์๋๋ค.JSX๋ javascript ํ์ฅํ ๋ฌธ๋ฒ์ผ๋ก ๋ฐ๋ฒจ๋ฑ๋ฑ์
cometruedream.tistory.com
react-query ๋ฐ์ดํฐ ํ๋ฆฌํ์นญ ์ฌ์ฉ๋ฒ์ ๋ํด ์์๋ณด๊ธฐ
https://cometruedream.tistory.com/251
[React-query] ๋ฐ์ดํฐ ํ๋ฆฌํ์นญ ์ฌ์ฉ๋ฒ ์ ๋ฆฌ
๐คทโ๏ธ ๋ณธ๋ก ์ ์์ํ์คํ ๊ฐ๋ฐ์ ์งํํ๋ฉด์ ์ฌ์ฉ์์ ์ ์ฅ์ ์ฐ์ ์ผ๋ก ํ์ฌ ์ฌ์ฉ์ ๊ฒฝํ์ ์ต์ฐ์ ์ผ๋ก ๊ฐ๋ฐํ๋ ค ๋ ธ๋ ฅํฉ๋๋ค. ์ผ๋ง ์ ์ ์ฝ์ ์ฑ ์์"๊ฐ๋ฐํ๋ ์ฌ๋์ด ์๊ณ ๋กญ๋ค๋ฉด ์ฌ์ฉํ
cometruedream.tistory.com
refetch ์ต์ ๊ณผ ์ฌ์ฉ๋ฒ ์ด ์ ๋ฆฌ
https://cometruedream.tistory.com/252
[React-query] refetch ์ต์ ๊ณผ ์ฌ์ฉ๋ฒ ์ด ์ ๋ฆฌ
๐คทโ๏ธ ๋ณธ๋ก ์ ์์react-query๋ React์์ ๋ฐ์ดํฐ๋ฅผ ๊ฐ์ ธ์ค๊ณ , ์บ์ฑํ๊ณ , ๋๊ธฐํํ๊ณ , ๋ฐ์ดํฐ ๊ด๋ฆฌ๋ฅผ ์ํ ํํฌ์ ์ ํธ๋ฆฌํฐ๋ฅผ ์ ๊ณตํ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ๋๋ค. ์ด ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ํ์ฉ์ React์ ์ ๋ฐ
cometruedream.tistory.com
๐คทโ๏ธ useMutation ๊ฐ๋ ?
useMutation์ React Query์์ ์ ๊ณตํ๋ ํ ์ผ๋ก ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๋ ์์ (HTTP ๋ฉ์๋: POST, PUT, PATCH, DELETE)์ ์ฒ๋ฆฌํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
useMutation์ ์๋ฒ ์ํ์ ํด๋ผ์ด์ธํธ ์ํ๋ฅผ ๋๊ธฐํํ๋๋ฐ ๋งค์ฐ ํจ์จ์ ์ด๋ฉฐ, ์ ์ฉํ ๊ธฐ๋ฅ์ ์ ๊ณตํฉ๋๋ค.
useMutation ์ ์ํ ๊ธฐ๋ฅ๋ค์ ํ์ฉํด์ ๋ฐ์ดํฐ์ ์ํ๊ด๋ฆฌ๋ฅผ ๋ณด๋ค ํจ์จ์ ์ผ๋ก ํ ์ ์์ต๋๋ค.
๋ฆฌ์กํธ ์ธ๊ธฐ ์๋ ์ด์ ?
ํ๋ก ํธ๊ฐ๋ฐ์๊ฐ ๋ฆฌ์กํธ๋ฅผ ์ข์ํ๋ 8๊ฐ์ง ์ด์
๋ฆฌ์กํธ๋ ํ์ด์ค๋ถ์์ ๊ฐ๋ฐํ ์๋ฐ์คํฌ๋ฆฝํธ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ก, ์ฌ์ฉ์ ์ธํฐํ์ด์ค(UI)๋ฅผ ๊ตฌ์ถํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค. 2013๋ ์ฒ์ ์ถ์๋ ์ดํ๋ก, ๋ฆฌ์กํธ๋ ๋น ๋ฅด๊ฒ ์ธ๊ธฐ๋ฅผ ์ป์์ต๋๋ค. ํ๋ก ํธ๊ฐ๋ฐ์๊ฐ
fnfentermagazine.com
๐คทโ๏ธ useMutation ์ฌ์ฉ๋ฒ?
Mutation์ ๊ธฐ๋ณธ ์ฌ์ฉ๋ฒ
- useMutation ํ ์ ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ๋ณ๊ฒฝํ๋ ๋น๋๊ธฐ ํจ์์ ํจ๊ป ์ฌ์ฉ๋ฉ๋๋ค.
- ์์
import { useMutation } from 'react-query';
import axios from 'axios';
const createPost = async (newPost) => {
const response = await axios.post('/posts', newPost);
return response.data;
};
const MyComponent = () => {
const { mutate } = useMutation(createPost);
const handleCreatePost = () => {
mutate({ title: 'New Post', content: 'Hello World' });
};
return (
<div>
<button onClick={handleCreatePost}>Create Post</button>
{mutation.isLoading && <p>Creating post...</p>}
{mutation.isError && <p>Error creating post</p>}
{mutation.isSuccess && <p>Post created successfully!</p>}
</div>
);
};
์์ ์์ ์ฒ๋ผ ๊ฐ์ฅ ๊ธฐ๋ณธ์ ์ธ useMutation ์ฌ์ฉ๋ฒ์ด๋ฉฐ HTTP ๋ฉ์๋ POST ์์ฒญ์ ์ฒ๋ฆฌํ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
useMutation ํ ์ ๊ฐ์ฅ ์ค์ํ 4๊ฐ์ง์ ์ฝ๋ฐฑ ์ต์
- useMutation ํ ์ ‘onSuccess’, ‘onError’, ‘onSettled’์ ๊ฐ์ ๋ค์ํ ์ฝ๋ฐฑ ์ต์ ์ ์ ๊ณตํฉ๋๋ค.
- ์์
const mutation = useMutation(createPost, {
onSuccess: (data) => {
console.log('์๋ฒ์ ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ:', data);
},
onError: (error) => {
console.error('์๋ฒ์ ํต์ ์ค๋ฅ:', error);
},
onSettled: () => {
console.log('์๋ฒ์ ํต์ ์ด ์คํจํ๋ ์ํ๋ ํธ์ถ');
},
});
์์ ์์ ์ฒ๋ผ useMutation ํ ์ 4๊ฐ์ง ์ฌ์ฉ๋ฐฉ๋ฒ์ ๋๋ค.
onMutate, onSuccess, onError, onSettled ์ต์ ์์๋ณด๊ธฐ
- onMutate
- useMutation ํ ์ด ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด๊ธฐ ์ง์ ์ ํธ์ถ๋ฉ๋๋ค.
- ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ๋ณด๋ด๊ธฐ ์ ์ ์ฒ๋ฆฌํด์ผ ๋๋ ๋ก์ง์ onMutate์์ ์ฒ๋ฆฌํฉ๋๋ค. ์: ์๋ฒ์ ํต์ ์ง์ ๋ก๋ฉ ์ํ๋ฅผ ํ์ํ ๋ ๋ง์ด ์ฌ์ฉ๋ฉ๋๋ค.
- onSuccess
- ์๋ฒ์ ์์ฒญ์ด ์ฑ๊ณต์ ์ผ๋ก ์๋ฃ๋๊ณ ์๋ฒ๊ฐ ์๋ต๊ฐ์ ๋๋ ค์คฌ์ ๋ ํธ์ถ๋ฉ๋๋ค.
- ์๋ฒ์ ์์ฒญ์ด ์ฑ๊ณตํ๊ณ ์ฒ๋ฆฌํด์ผ๋๋ ๋ก์ง์ onSuccess์์ ์ฒ๋ฆฌํฉ๋๋ค. ์: ์ฑ๊ณต ๋ฉ์์ง, ๋ค๋ฅธ ํ๋ฉด์ผ๋ก ์ด๋์ํฌ ๋ ์ฌ์ฉ๋ฉ๋๋ค.
- onError
- ์๋ฒ์ ์์ฒญ์ด ์คํจํ์ ๋ ํธ์ถ๋ฉ๋๋ค.
- ์์ฒญ์ด ์คํจํ์ ๋ ์ฒ๋ฆฌํด์ผ ๋๋ ๋ก์ง์ onError์์ ์ฒ๋ฆฌํฉ๋๋ค. ์: ์๋ฒ์ ํต์ ์คํจ ์ ์๋ฌ๋ฉ์์ง, ์ฌ์ฉ์์ ๊ฐ์ด๋๋ฅผ ์์ฒญํ ์ ์์ต๋๋ค.
- onSettled
- ์๋ฒ์ ์์ฒญ์ด ๋๋ ํ ์ฑ๊ณตํ๋ ์คํจํ๋ ํญ์ ํธ์ถ๋ฉ๋๋ค. ํ์ ์๋ ๊ฒฝ์ฐ์๋ ํธ์ถ์ ์ ํด๋ ๋ฉ๋๋ค.
- ์์ฒญ์ด ๋๋๊ณ ํญ์ ์ฒ๋ฆฌํด์ผ ๋๋ ๋ก์ง์ onSettled์์ ์ฒ๋ฆฌํฉ๋๋ค. ์: ์๋ฒ์ ํต์ ์ด ์๋ฃ ํ ๋ก๋ฉ๋ฐ๋ฅผ ํด์ฒดํ๋ ๋ฐ ์ฌ์ฉ๋ฉ๋๋ค.
์์ 4๊ฐ์ง ์ต์ ์ ์ดํดํ ์ ์๋ ์์
import { useMutation } from '@tanstack/react-query';
const sendText = async (message) => {
// ์๋ฒ์ ๋ฉ์์ง๋ฅผ ๋ณด๋ด๋ ํจ์
};
const useSendText = () => {
const { mutate: send } = useMutation({
mutationFn: sendText,
onMutate: () => {
// ๋ฉ์์ง๋ฅผ ๋ณด๋ด๊ธฐ ์ง์ ์ ํธ์ถ
console.log('๋ฌธ์๋ฅผ ๋ณด๋ด๋ ์ค...');
},
onSuccess: () => {
// ๋ฉ์์ง๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ๋ณด๋ธ ํ ํธ์ถ
console.log('๋ฌธ์๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ๋ณด๋์ด์!');
},
onError: (error) => {
// ๋ฉ์์ง๋ฅผ ๋ณด๋ด๋ ์ค ์ค๋ฅ๊ฐ ๋ฐ์ํ๋ฉด ํธ์ถ
console.log('๋ฌธ์ ๋ณด๋ด๊ธฐ์ ์คํจํ์ด์. ๋ค์ ์๋ํด ์ฃผ์ธ์.');
},
onSettled: () => {
// ๋ฉ์์ง ๋ณด๋ด๊ธฐ๊ฐ ๋๋๋ฉด ํญ์ ํธ์ถ (์ฑ๊ณต์ด๋ ์คํจ๋ )
console.log('๋ฌธ์ ๋ณด๋ด๊ธฐ ์์
์ด ๋๋ฌ์ด์.');
},
});
return send;
};
useMutation ์ค์ ์์
import { useMutation, useQueryClient } from 'react-query';
import axios from 'axios';
const deletePost = async (postId) => {
await axios.delete(`/posts/${postId}`);
};
const MyComponent = () => {
const queryClient = useQueryClient();
const { mutate: send } = useMutation(deletePost, {
onSuccess: () => {
queryClient.invalidateQueries('posts');
},
});
const handleDelete = (postId) => {
send(postId);
};
return (
<div>
<button onClick={() => handleDelete(1)}>Delete Post</button>
{mutation.isLoading && <p>Deleting post...</p>}
{mutation.isError && <p>Error deleting post</p>}
{mutation.isSuccess && <p>Post deleted successfully!</p>}
</div>
);
};
์์ ์์ ์ฒ๋ผ ์ค์ ๋ง์ด ์ฌ์ฉ๋๋ useMutation ๋ก์ง์ ๋๋ค.
์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ํต์ ํ onSuccess ํธ์ถํ๊ณ ๋ณ๊ฒฝํ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฐ์ดํธํ๋ react-query ์ ๊ณตํ๋ invalidateQueries ๋ฉ์๋๋ฅผ ์คํํ์ต๋๋ค.
queryClient.invalidateQueries ๋ฌด์์ธ๊ฐ?
queryClient.invalidateQueries ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ํน์ ์ฟผ๋ฆฌ์ status๋ฅผ ์ฆ์ stale๋ก ๋ณ๊ฒฝํ์ฌ ๋ฐฑ๊ทธ๋ผ์ด๋ ๋จ์์ refetch๊ฐ ๋ฐ์ํ์ฌ ๋ณ๊ฒฝ๋ ๋ฐ์ดํฐ๋ฅผ ์ ๋ฐ์ดํธํ ์ ์์ต๋๋ค.
useMutation ํ ์ค์์ ์๋ฒ์ ๋ฐ์ดํฐ๋ฅผ ์ฑ๊ณต์ ์ผ๋ก ํต์ ํ์ ๋ง์ด ์ฌ์ฉ๋๋ ๋ฉ์๋์ ๋๋ค.
๐คทโ๏ธ ๋ง์ง๋ง์ผ๋ก
useMutation์ ๊ฐ๋ ๊ณผ ํ์ฉํ๋๋ฐ ๊ฐ์ฅ ์ค์ํ 4 ์๊ธฐ์ ์ฝ๋ฐฑํจ์๋ฅผ ์์๋ณด์์ต๋๋ค.
๊ฐ ์ฝ๋ฐฑ ํจ์๋ ์๋ฒ ์์ฒญ์ ๋ค๋ฅธ ๋จ๊ณ์์ ํธ์ถ๋๋ฉฐ ๊ฐ๊ฐ์ ์ฝ๋ฐฑ ํจ์๋ฅผ ํตํด์ ํจ์จ์ ์ผ๋ก ์๋น์ค ๋ก์ง์ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
useMutation ํ ์ค๋ ์๋ฒ์ ํด๋ผ์ด์ธํธ์ ์ํ๋ฅผ ๋ค๋ฃจ๋๋ฐ ๋งค์ฐ ํจ์จ์ ์ด๋ฉฐ ๋ค์ํ ์ต์ ๋ค์ ํ์ฉํด์ ์ฌ์ฉ์์๊ฒ ์ข์ UI/UX ๊ฒฝํ์ ์ ๊ณตํ ์ ์์ต๋๋ค.
์ฌ๋ฐ๋ ์ค๋์ ๋ ๋ณ ์ด์ธ ๋ณด๊ณ ๊ฐ์ธ์!
https://fnfentermagazine.com/%ec%8a%a4%ec%bd%94%ed%94%84%ec%9d%98-%ea%b0%9c%eb%85%90/
[์๋ฐ์คํฌ๋ฆฝํธ 1ํ] ์๋ฐ์คํฌ๋ฆฝํธ ์ค์ฝํ์ ๊ฐ๋ ๊ณผ ์์ ์์๋ณด๊ธฐ
์๋ฐ์คํฌ๋ฆฝํธ ์ค์ฝํ์ ๊ฐ๋ , ์ค์ฝํ(scope)๋ ๋ฒ์๋ฅผ ์๋ฏธํ๋ฉฐ ์๋ฐ์คํฌ๋ฆฝํธ ๋ณ์์ ๋ํ ์ ๊ทผ ๊ถํ์ ์ ์ํ๋ ๊ฒ์ ๋๋ค. ์ฆ, ์ค์ฝํ๋ ๋ณ์๊ฐ ์ ๊ทผ ๊ฐ๋ฅํฉ ๋ฒ์๋ฅผ ๋ํ๋ด๋ฉฐ ๋ณ์์ ์ ํจ ๋ฒ์
fnfentermagazine.com
https://cometruedream.tistory.com/247
[React] Tailwind ํ์ค, ๋์ค, ์ธ์ค ํจ๊ณผ className ์ปค์คํ
๐คทโ๏ธ Tailwind ํ์ค, ๋์ค, ์ธ์ค ํจ๊ณผํ๋ก์ ํธ ์งํ์ค ๋ฐฐ๋ ๋งํฌ์ URL ๊ธธ์ด๊ฐ ๋๋ฌด ๊ธธ์ด์ 3์ค ํจ๊ณผ ์ฒ๋ฆฌ๋ฅผ ํด์ผ ํ์ต๋๋ค. React + Tailwind CSS ์ ํ ๋ ํ๋ก์ ํธ ์ฌ์ CSS ํ์ผ & style ํ๊ทธ๋ฅผ ์ฌ์ฉํ
cometruedream.tistory.com
https://cometruedream.tistory.com/243
NestJS Lifecycle (์๋ช ์ฃผ๊ธฐ) ๊ฐ๋
๐คทโ๏ธ ๋ณธ๋ก ์ ์์ Nest JS ๊ฐ๋ ?Nest JS๋ Node JS ๊ธฐ๋ฐ์ผ๋ก ํ ์๋ฒ ์ดํ๋ฆฌ์ผ์ด์ ํ๋ ์์ํฌ ์ ๋๋ค. ์๋ฐ์คํฌ๋ฆฝํธ๋ ์๋นํ ์ค๋ซ๋์ Express ๊ธฐ๋ฐ์ผ๋ก ์๋ฒ ์ดํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ์์ ์๋์ ์ธ ์
cometruedream.tistory.com
https://cometruedream.tistory.com/242
๋ฆฌ์กํธ Vite Proxy ํ์ฉํ CORS ์ค๋ฅ ํด๊ฒฐ
๐คทโ๏ธ ๋ณธ๋ก ์ ์์ํ๋ก ํธ์๋ ๋ฒ๋ค๋ฌ ๊ฐ๋ ๊ณผ webpack vs vite ๋น๊ต์ ๋ํด์ ๊ณต๋ถ๋ฅผ ํ๊ณ ๊ธ์ ๋ณด์๋ฉด ๋ ๋ง์ ๋์์ด ๋ฉ๋๋ค^^ํ๋ก ํธ์๋ ๊ฐ๋ฐ์ ์ํ ๋ฒ๋ค๋ฌ ๊ฐ๋ ๊ณผ webpack vs vite ๋น๊ตhttps://comet
cometruedream.tistory.com
https://cometruedream.tistory.com/241
React ํด๋๊ตฌ์กฐ FSD ๊ธฐ๋ฅ ๋ถํ ์ค๊ณ ์ํคํ ์ฒ
๐คทโ๏ธ ๋ณธ๋ก ์ ์์ํ๋ก์ ํธ๋ฅผ ์์ํ๊ธฐ์ ์์ ํด๋ ๊ตฌ์กฐ, ์ค๊ณ์ ๋ํ ์ํคํ ์ฒ๋ฅผ ๋ง๋๋ ๊ฒ์ ์๋นํ ์ด๋ ต๋ค. ์ด๋ฒ ํ๋ก์ ํธ์ React FSD ํด๋๊ตฌ์กฐ ์ํคํ ์ฒ๋ฅผ ์ค๊ณํ ์์ ์ด๋ผ์ FSD ์ํคํ
cometruedream.tistory.com
https://cometruedream.tistory.com/244
์ฝ๊ฒ ์ดํดํ๊ณ ์ฌ์ฉํ ์ ์๋ Prisma ๋ช ๋ น์ด ์ ๋ฆฌ
๐คทโ๏ธ Prisma ๋ช ๋ น์ด ๋ณธ๋ก ์ ์์ Prisma๋?Nest JS ํ๋ ์์ํฌ์ Prisma ORM์ ํ์ฉํด์ ํ๋ก์ ํธ๋ฅผ ์งํํ๋ฉด์ Prisma๋ Node JS ๊ธฐ๋ฐ์ ํ๋ ์์ํฌ/๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ํธ์์ฉ์ด ์๋๋ฉฐ Prisma + DB ์ฐ๋์ผ
cometruedream.tistory.com
'React' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
๋ฆฌ์กํธ ์ ์ด vs ๋น์ ์ด ์ปดํฌ๋ํธ ์์๋ณด๊ธฐ (0) | 2024.08.02 |
---|---|
๋ฆฌ์กํธ useLayoutEffect ๊ฐ๋ ๋ฐ ์ฌ์ฉ๋ฒ (36) | 2024.07.31 |
[React-query] ๋ฐ์ดํฐ ํ๋ฆฌํ์นญ ์ฌ์ฉ๋ฒ ์ ๋ฆฌ (1) | 2024.06.19 |
[React] Tailwind ํ์ค, ๋์ค, ์ธ์ค ํจ๊ณผ className ์ปค์คํ (1) | 2024.06.03 |
Next JS์์ tailwind ์ ์ฉ ์๋ ๋ ํด๊ฒฐ๋ฐฉ๋ฒ (1) | 2024.05.17 |