Programing

Redex 및 라우터 - 서버 렌더링으로 응답

c10106 2022. 4. 2. 09:06
반응형

Redex 및 라우터 - 서버 렌더링으로 응답

비동기 호출로 서버 렌더링을 작동시키려 한다.문제는 렌더링 전에 데이터가 다운로드되지 않는다는 겁니다.

내 코드(github: https://github.com/tomekbuszewski/server-rendering)에서도 사용 가능)

server.js

require('babel-register');

import express from 'express';
import path from 'path';

import React from 'react';
import { renderToString } from 'react-dom/server';
import { Provider } from 'react-redux';
import { getState } from 'redux';
import { match, RouterContext } from 'react-router'

import routes from './app/routes';
import store from './app/store';

const app = express();
const port         = 666;

app.get('/', (req, res) => {
  match({ routes, location: req.url }, (error, redirectLocation, renderProps) => {
    if (renderProps) {
      console.log(renderProps.components);
      res.send(renderToString(
        <Provider store={store}>
          <RouterContext {...renderProps} />
        </Provider>
      ))
    } else {
      console.log('err')
    }
  });
});

app.use('/public', express.static(path.join(__dirname, 'public')));
app.use('/data', express.static(path.join(__dirname, 'data')));

app.listen(port);
console.log(`localhost:${port}`);

routes.js.

import React from 'react';
import { Router, Route, browserHistory } from 'react-router';

import App from './Components/App';

const routes = (
  <Router history={browserHistory}>
    <Route path="/" component={App} />
  </Router>
);

export default routes;

앱 구성 요소 가져오기 기능:

const fetch = (dispatch) => {
    const endpoint = '/data/index.json';

    axios.get(endpoint).then((res) => {
        Array.prototype.forEach.call(res.data, d => {
            const payload = {
                id:    d.id,
                title: d.title
            };

            dispatch({type: 'ADD_CONTENT', payload});
        });
    });
};

'ADD_Content' 액션을 발송하는 경우:

case 'ADD_CONTENT':
  return { ...state, data: [...state.data, action.payload] };

모든 것이 고객측에서 훌륭하게 작동한다.

  1. 저장소에 데이터가 올바르게 로드될 때 약속을 이행하는 리듀렉스 조치

예를 들면 다음과 같다.

const fetch = (dispatch) => {
    const endpoint = '/data/index.json';

    return axios.get(endpoint).then((res) => {
        Array.prototype.forEach.call(res.data, d => {
            const payload = {
                id:    d.id,
                title: d.title
            };

            dispatch({type: 'ADD_CONTENT', payload});
        });
    });
};
  1. 구성 요소를 로드하기 전에 이러한 작업을 호출하는 리듀렉스 연결과 같은 래퍼를 사용해야 한다.

예제에서 라우팅된 구성 요소는App

이 경우, 데이터를 미리 로드하는 필요한 환원 작업으로 해당 구성 요소를 장식하십시오.

import { asyncConnect } from 'redux-connect';

@asyncConnect([{
    promise: ({ store: { dispatch } }) => {
        // `fetch` is your redux action returning a promise
        return dispatch(fetch());
    }
}])
@connect(
    state => ({
        // At this point, you can access your redux data as the
        // fetch will have finished 
        data: state.myReducer.data
    })
)
export default class App extends Component {
    // ...the `data` prop here is preloaded even on the server
}

@connect상단의 컨테이너에 있는 데이터를 사용하지 않는 경우, 스토어는 앱 전체에서 사용 가능하지만,@asyncConnect직접 호출한 구성요소를 장식해야 함react-router, 렌더링된 트리의 중첩된 구성요소에 사용할 수 없거나(현재까지), 초기 렌더링 중에 구문 분석되지 않음

컴포넌트 트리의 렌더링은 서버에서 한 번만 발생하며, 그 기능은 컴포넌트 자체에 의해 호출될 수 없기 때문에, 로딩하기 에, 다음 작업을 통해 호출되어야 한다. redux-connect예를 들어, 약속을 지원하는 환원 조치(Redex Action)를 참조하십시오.redux-thunk미들웨어

참조URL: https://stackoverflow.com/questions/39206676/react-with-redux-and-router-server-rendering

반응형