Next.js에서 Redx를 사용하는 것은 안티패턴입니까?
Next.js 앱을 만들고 있는데 현재 Redux를 사용하고 있습니다.조립을 하고 있기 때문에 Redux를 꼭 사용할 필요가 있는지, 실제로 안티패턴을 사용할 필요가 있는지 궁금합니다.제 논리는 이렇습니다.
Next Next.js "Redux Store" 를 .App「」가 getInitialProps방법.이를 통해 Next.js에서 제공하는 자동 정적 최적화를 비활성화합니다.
반면 클라이언트 측에 Redx를 포함시키면 앱이 마운트된 후에만 Redux 저장소가 리셋됩니다.들어 클라이언트하는 Next, "Redux"와 할 는 "Next"를 사용합니다.pages/projects/[id]이 페이지는 서버 측에서 렌더링되며 스토어에 있던 정보를 다시 가져와야 합니다.
질문은 다음과 같습니다.
- 이러한 상황에서 Redux 스토어의 이점은 무엇입니까?
- 해야 합니까?
App동동 정정 ?최 최? ?? ??? - Next 9에서 Next.js 9.3을 사용하여 더 ?
getStaticProps기타 데이터 가져오기 방법 - 내가 뭘 빼놓았나요?
getInitialProps를 사용하는 커스텀 앱이 있는 경우 Next.js에서 제공하는 자동 정적 최적화는 모든 페이지에서 비활성화됩니다.
맞아요, 이런 식으로 접근하면요
더 좋은 방법은 없을까?
예, Redux 공급자를 래퍼로 생성하고 필요한 구성 요소를 래핑할 수 있습니다. 그러면 Redux 컨텍스트가 자동으로 초기화되어 해당 구성 요소 내에서 제공됩니다.
예:
const IndexPage = () => {
// Implementation
const dispatch = useDispatch()
// ...
// ...
return <Something />;
}
IndexPage.getInitialProps = ({ reduxStore }) => {
// Implementation
const { dispatch } = reduxStore;
// ...
// ...
}
export default withRedux(IndexPage)
이제 전체 앱에 대한 최적화를 해제하지 않고 상태 관리가 필요한 페이지에만 Redux를 사용할 수 있습니다.
"Next.js와 함께 Redx를 사용하는 것은 안티패턴입니까?"라는 질문에 대한 답변
아니요, 하지만 제대로 사용해야 해요.
방법에 대한 자세한 내용은 https://github.com/vercel/next.js/tree/canary/examples/with-redux를 참조하십시오.
이게 도움이 됐으면 좋겠다
우리는 주로 두 가지 이유로 Redux를 사용합니다.
1-컴포넌트 간에 데이터를 전달합니다.
만약 당신이 레덕스를 사용하지 않는다면, 당신은 소품 드릴링을 할 필요가 있습니다.사용자가 로그인했는지 여부를 판단하기 위해 데이터를 가져와 redux 저장소에 저장한 후 Header 구성 요소가 저장소에 연결하여 인증 정보를 가져옵니다.redux를 사용하지 않을 경우 각 페이지에서 사용자를 가져와 Header 구성 요소에 전달해야 합니다.
Next.js는 모든 페이지를 프리렌더합니다.즉, Next.js는 클라이언트 측 JavaScript에 의해 모든 작업을 수행하는 대신 각 페이지에 대해 미리 HTML을 생성합니다.프리렌더링으로 퍼포먼스와 SEO를 향상시킬 수 있습니다.next-redux-wrapper 패키지에서는 redux를 자동 정적 최적화와 함께 사용할 수 있습니다.링크를 클릭하면 "Next.js는 일반적인 get을 제공합니다.MyApp 클래스를 사용할 때 InitialProps는 래퍼에 의해 선택되므로 앱을 확장해서는 안 됩니다. 자동 정적 최적화:"에서 제외됩니다.이 패키지는 프로젝트용으로 셋업되어 있어 셋업이 간단합니다.
그러나 redux를 사용하는 것의 단점은 캐싱이 아니라는 것입니다.데이터를 저장한 후 정기적으로 다시 추출하여 최신 상태를 확인합니다.그리고 이것은 매우 비싼 작업입니다.redux의 캐시를 실현하기 위해 reselect 라이브러리를 사용합니다.즉, redux와 더불어 프로젝트에 대한 의존도가 높아지며 더 많은 코드를 작성할 수 있습니다.
next.js에서 작성한 멋진 패키지 swr이 있습니다.Stale-While-Revalidate.먼저 캐시(cache)에서 데이터를 반환한 후 가져오기 요청을 전송하고 마지막으로 업데이트된 데이터를 다시 제공합니다.각 페이지마다 이것을 사용합니다.
import useSWR from "swr";
export const useGetUser = () => {
// fetcher can be any asynchronous function which returns the data. useSwr will pass "/api/v1/me" to fetcher
const { data, error, ...rest } = useSWR("/api/v1/me", fetcher);
// !data && !error if both true, loading:true, data=null=>!data=true, error=null => !error=true
return { data, error, loading: !data && !error, ...rest };
};
여기 소중한 페처가 있다
export const fetcher = (url: string) =>
fetch(url).then(
async (res: Response): Promise<any> => {
const result = await res.json();
if (res.status !== 200) {
return Promise.reject(result);
} else {
return result;
}
}
);
2- API 요청 작성.
프로젝트를 위해 리덕스 스토어를 설정했는데 설정한 텍스트 에디터와 충돌했습니다.레독스가 편집기를 막고 있어서 편집기에 쓴 텍스트로 스토어를 채울 수 없었습니다.그래서 api를 가져올 때 재사용 가능한 훅을 사용했습니다.처음에는 은근히 보이지만 분석해보면 이해가 될 거예요.
export function useApiHandler(apiCall) {
// fetching might have one those 3 states. you get error, you fetch the data, and you start with the loading state
const [reqState, setReqState] = useState({
error:null,
data:null,
loading:true, // initially we are loading
});
const handler = async (...data) => {
setReqState({ error: null, data: null, loading: true });
try {
// apiCall is a separate function to fetch the data
const res = await apiCall(...data);
setReqState({ error: null, data: res.data, loading: false });
alert(res.data);// just to check it
return res.data;
} catch (e) {
// short circuting in or. if first expression is true, we dont evaluate the second.
// short circuting in and. if first expression is true, result is the second expression
const message =
(e.response && e.response.data) || "Ooops, something went wrong...";
setReqState({ error: message, data: null, loading: false });
return Promise.reject(message);
}
};
return [handler, { ...reqState }];
}
단순한 apiCall 함수
const createBlog = (data) => axios.post("/api/v1/blogs", data);
그 후, 다음과 같이 사용합니다.
export const useCreateBlog = () => useApiHandler(createBlog);
redux 설정은 간단하기 때문에 사람들은 앱의 성능에 대해 걱정하지 않고 설정하기만 하면 됩니다.제 생각에는 큰 앱을 가지고 계신 분이나 graphql에 익숙하신 분은 Apollo를 사용하시면 됩니다.여기 아폴로를 국가 경영으로 사용하는 것에 대한 아이디어를 얻을 수 있는 좋은 기사가 있습니다. 아폴로를 국가 경영으로 사용하는 것입니다.저는 큰 e커머스 웹사이트를 구축했고, 새로운 앱에서 redux를 사용했습니다. 왜냐하면 비교적 작기 때문에 next js를 사용하지 않고 더 복잡하게 만들고 있습니다.
Redux 툴킷 쿼리
생각합니다redux toolkit query (RTK query)레독스 생태계의 가장 큰 개선입니다.실제로는 redux-toolkit 라이브러리 위에 구축되어 있습니다. redux-toolkitimmer.diag를 사용하여 redux 코드를 훨씬 쉽게 작성하고 상태를 쉽게 업데이트 할 수 있었습니다.
"RTK 쿼리"를 사용하여 데이터 가져오기 및 상태 관리를 함께 처리할 수 있습니다.모든 데이터 가져오기는 하나의 API로 결합되며 데이터를 캐시하거나 캐시를 비활성화하거나 쿼리를 다시 설정할 수 있습니다.그것은 실제로 그 조합이 하고 있는 것이다.swr그리고.context Api하고 있습니다. swr과 context api를 사용한 상태 관리
Redux를 사용하는 경우 _app.js에서 getInitialProps를 사용할 필요가 없습니다.
next-redux-wrapper를 사용하여 _app.js export를 랩핑할 수 있습니다.
스토어 예에서는 next-redux-wrapper와 thunk를 사용합니다.
import { createStore, applyMiddleware } from 'redux';
import { createWrapper } from 'next-redux-wrapper';
import { composeWithDevTools } from 'redux-devtools-extension';
import thunkMiddleware from 'redux-thunk';
import rootReducer from './rootReducer';
const bindMiddleware = middleware => {
return composeWithDevTools(applyMiddleware(...middleware));
};
const initStore = (initialState = {}) => {
return createStore(rootReducer, initialState, bindMiddleware([thunkMiddleware]));
};
export const wrapper = createWrapper(initStore, { debug: true });
그런 다음 _app.js 내에서 이 컴포넌트를 기능 컴포넌트로 내보냅니다.
const App = ({ Component, pageProps }) => {
return (
<Component {...pageProps} />
)
}
export default wrapper.withRedux(App);
마법처럼 작동한다.하이드레이션 sr -> csr만 실행해 주세요.
개인적으로 Redux를 사용하는 것은 어떤 경우에도 좋은 생각이 아니라고 생각합니다.예를 들어 useContext를 사용하거나 중앙 집중식 스토리지가 mobx에 매우 필요한 경우 사용하는 것이 좋습니다.그러나 실제로 getInitialProps를 사용하지 않고 SSR에서 Redx를 사용하는 간단한 방법이 있습니다.
여기서 중요한 점이 있습니다.제가 제시한 솔루션은 서버상의 모든 페이지의 렌더링을 사용하지 않는 경우에만 적용할 수 있습니다.첫 번째 렌더링 후 경로를 따라가면 어플리케이션은 다음 페이지를 자동으로 렌더링합니다.이 솔루션에서는 서버 측에서 스토어가 1회 초기화되어 렌더링 결과가 클라이언트에 전송되는 것을 전제로 하고 있습니다.루트를 탐색할 때마다 서버 상에서 페이지를 렌더링해야 하고 스토어 상태를 저장해야 하는 경우 next-redux-wrapper를 찾는 것이 좋습니다.
따라서 getServerSideProps에서 스토어를 초기화하려면 스토리지 초기화 파일을 다음과 같이 변경해야 합니다(다른 Import가 있을 수 있습니다).
import { createStore, applyMiddleware } from 'redux';
import thunkMiddleware from 'redux-thunk';
import { composeWithDevTools } from 'redux-devtools-extension/developmentOnly';
let storeInstance: any;
export const makeStore = (initialState: {}) => {
storeInstance = createStore(
Reducers,
initialState,
composeWithDevTools(applyMiddleware(thunkMiddleware)) // Optional, but is a handy thing
);
return storeInstance;
};
// initializeStore used for pages that need access to store at getServerSideProps
export const initializeStore = (preloadedState) => {
let reInitiatedStore = storeInstance ?? makeStore(preloadedState)
// After navigating to a page with an initial Redux state, merge that state
// with the current state in the store, and create a new store
if (preloadedState && storeInstance) {
reInitiatedStore = makeStore({ ...storeInstance.getState(), ...preloadedState});
// Reset the current store
storeInstance = undefined;
}
// Keep in mind that in some cases this can cause strange
// and difficult to track errors, so whether or not
// to uncomment next lines depends on the architecture of your application.
// if (typeof(window) === 'undefined') {
// return reInitiatedStore; // For SSG and SSR always create a new store
// }
// Create the store once in the client
if (!storeInstance) {
storeInstance = reInitiatedStore;
}
return reInitiatedStore;
}
그 후 getServerSideProps의 서버 측에 스토어가 필요한 페이지에서 initializeStore를 간단하게 사용할 수 있습니다.
import { initializeStore } from '@Redux';
// Compnent code here...
export const getServerSideProps(context: any) {
const reduxStore = initializeStore();
// reduxStore = {
// dispatch: [Function (anonymous)],
// subscribe: [Function: subscribe],
// getState: [Function: getState],
// }
// Doing something with the storage...
const initialReduxState = storeInstance.getState(); // and get it state
return { props: { initialReduxState, ...someProps } };
}
또, _app.js의 스토어에 액세스 할 필요가 있는 경우는, 스토어를 다음과 같이 정의할 필요가 있습니다.
const store = initializeStore(pageProps.initialReduxState);
next.js는 서버 사이드 렌더링 설정을 단순화하는 React 위에 있는 프레임워크에 불과하지만 여전히 React입니다.그리고 React/Redux 콤보는 매우 인기가 있고 지금도 자주 사용되고 있기 때문에, 대답은 필요 없지만, 완전히 가능합니다!앱이 클수록, 기능적인 프로그래밍을 좋아할수록, Redux가 좋은 옵션이 될 가능성이 높아집니다!
언급URL : https://stackoverflow.com/questions/60626451/is-using-redux-with-next-js-an-anti-pattern
'programing' 카테고리의 다른 글
| PowerShell에서 문자열을 변수와 연결하려면 어떻게 해야 합니까? (0) | 2023.08.13 |
|---|---|
| JUNit을 사용한 유닛 테스트에서 스프링이 자동 배선되지 않음 (0) | 2023.08.13 |
| '@Bean' 메서드에서 '@ConfigurationProperties' 주석 사용 (0) | 2023.03.26 |
| Angular 구성 파일JS (0) | 2023.03.26 |
| 메인 어플리케이션에서 Spring Boot을 호출하는 서비스를 호출하는 방법 (0) | 2023.03.26 |