
서버 사이드에서 Apollo 상태를 재수화하고 사용자 정의 Redux 상태를 통합하는 방법은 무엇인가요?
React Apollo를 처음 사용하면 서버 측에서 클라이언트로 상태를 다시 로드하는 문제에 직면할 수 있습니다. 걱정하지 마세요 – 혼자가 아닙니다! 이 문제 해결 안내서에서는 Apollo 상태를 다시로드하고 앱이 사전로드된 상태를 사용하지 않는 문제를 해결하는 단계를 살펴보겠습니다.
문제 이해하기
React Apollo를 사용할 때, 앱이 컴포넌트를 렌더링 한 후에 API 호출 대신 Apollo에서 사전로드된 상태를 렌더링하는지 확인하는 것이 중요합니다. 적절한 구성 없이는 불필요한 API 요청이 발생하여 애플리케이션의 성능에 영향을 줄 수 있습니다.
Redux와의 통합
Redux와 Apollo를 통합할 때 Redux는 Apollo와 함께 사용자 정의 Redux 상태를 렌더링하지 않는다는 일반적인 문제가 발생할 수 있습니다. 이 문제를 해결하기 위해 다음의 단계를 따릅니다:
1. Server.js 코드
const HTML = ({ html, state }) => (
<html lang="en" prefix="og: http://ogp.me/ns#">
<head>
<meta charSet="utf-8" />
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
<meta httpEquiv="Content-Language" content="en" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
</head>
<body>
<div id="app" dangerouslySetInnerHTML={{ __html: html }} />
<script dangerouslySetInnerHTML={{
__html: `window.__STATE__=${JSON.stringify(state)};`,
}} />
<script src="/static/app.js" />
</body>
</html>
);
app.get('/*', (req, res) => {
const routeContext = {};
const client = serverClient();
const components = (
<StaticRouter location={req.url} context={routeContext}>
<ApolloProvider store={store} client={client}>
<WApp />
</ApolloProvider>
</StaticRouter>
);
getDataFromTree(components).then(() => {
const html = ReactDOMServer.renderToString(components);
const initialState = { apollo: client.getInitialState() };
res.send(`<!DOCTYPE html>\n${ReactDOMServer.renderToStaticMarkup(
<HTML
html={html}
state={initialState}
/>
)}`);
});
});
2. ApolloClient.js 코드
import ApolloClient, {
createNetworkInterface,
addTypeName,
} from 'apollo-client';
const client = new ApolloClient({
networkInterface: createNetworkInterface({ uri: testUrl }),
dataIdFromObject: ({ id }) => id,
reduxRootKey: state => state.apollo,
initialState: (typeof window !== 'undefined') ? window.__STATE__ : {},
});
export default client;
3. Store.js 코드
import { createStore, compose, applyMiddleware } from 'redux';
import { syncHistoryWithStore } from 'react-router-redux';
import thunk from 'redux-thunk';
import { createLogger } from 'redux-logger';
import client from '../apolloClient';
import rootReducer from '../Reducers';
const middlewares = [thunk, client.middleware()];
const enhancers = [];
if (!isProduction && isClient) {
const loggerMiddleware = createLogger();
middlewares.push(loggerMiddleware);
if (typeof devToolsExtension === 'function') {
const devToolsExtension = window.devToolsExtension;
enhancers.push(devToolsExtension());
}
}
const composedEnhancers = compose(
applyMiddleware(...middlewares),
...enhancers
);
const store = createStore(
rootReducer,
initialState,
composedEnhancers,
);
export default store;
4. 샘플 컴포넌트 코드
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { graphql } from 'react-apollo';
import gql from 'graphql-tag';
import * as postActions from '../../Redux/Actions/postActions';
class Home extends Component {
componentWillMount() {
// console.log('From Will Mount',this.props.posts)
}
renderAllPost() {
const { loading, posts } = this.props;
if (!loading) {
return posts.map(data => {
return <li key={data.id}>{data.title}</li>
});
} else {
return <div>loading</div>
}
}
render() {
console.log(this.props);
return (
<div>
{this.renderAllPost()}
</div>
);
}
}
const GetallPosts = gql`
query getAllPosts{
posts{
id
title
body
}
}
`;
const ContainerWithData = graphql(GetallPosts, {
props: ({ data: { loading, posts } }) => ({
posts,
loading,
}),
})(Home)
export default connect()(ContainerWithData);
결론
이 문제 해결 안내서의 단계를 따라 간다면 서버 측에서 클라이언트로 Apollo 상태를 성공적으로 다시 로드할 수 있습니다. Redux를 Apollo와 올바르게 통합하여 Apollo와 Redux 상태를 올바르게 렌더링하는 것을 기억하세요. 이러한 기술의 조합은 때로는 복잡할 수 있지만 올바른 접근 방식으로 강력하고 성능이 우수한 응용 프로그램을 구축할 수 있습니다.
즐거운 코딩하세요!
참고 자료 :
https://stackoverflow.com/questions/44614666/how-to-rehydrate-my-apollo-state-from-server-side
같은 카테고리의 다른 글 보기 :