2017-12-17 25 views
0

는 좀 돌아 오는 액션 연기 setTimeout을 사용 :ReactJS,의 setTimeout 문제

export const doLockSide = (lockObject) => (dispatch) => { 
    const timerId = setTimeout(() => { 
    dispatch({ 
     type: CONSTANTS.TOPICS_SET_CURRENT_TOPIC_LOCKED_SIDE, 
     payload: { id: lockObject.topicId, side: lockObject.side, locked: false } 
    }); 
    }, lockObject.unlockTimeout); 

    dispatch({ 
    type: CONSTANTS.TOPICS_SET_CURRENT_TOPIC_LOCKED_SIDE, 
    payload: { id: lockObject.topicId, side: lockObject.side, timerId, locked: true } 
    }); 
}; 

lockObject 서버에서 온다, 그래서이 코드는 비동기 돌아 오는 행동 체인의 일부입니다. 괜찮 았지만이 기능을 서버 측 렌더링 프로세스의 일부로 만들려고 시도했을 때 응용 프로그램이 고장났습니다. 브라우저와 NodeJS 런타임 환경의 차이점과 그 구현의 차이점은 setTimeout입니다. 구체적으로 내 timerId은 개체이기 때문에 Node에서 처리 할 수 ​​없지만 Redux 감속기는이를 정수로 처리합니다. 하지만 주요 문제는 서버 측 렌더링 중에 노드가 서버 측 콜백 setTimeout 콜백을 발생시키는 것입니다 ...

질문은입니다. 나는 앱 시작을 포함하여 어떤 경우에 연기되어야하는 약간의 redux 기반의 프로세스를 가지고있다. 서버 측 렌더링 요구 사항을 만족시키는 방법은 무엇입니까?

+0

모든 데이터가 반환 될 때까지 기다렸다가 클라이언트에게 응답을 보내야합니다. 여기 redux 페이지에 표시된 예를 살펴보십시오. https://redux.js.org/docs/recipes/ServerRendering.html#async-state-fetch –

+0

@MatanBobi 서버 측 렌더링 중에 필요한 모든 데이터가 fetchet되고 있습니다. , 그것은 문제가되지 않습니다. 문제는이 데이터를 기반으로 클라이언트 측에서 일부 작업을 연기하는 것입니다. 클라이언트는 렌더링 된 후 시간 초과를 실행해야합니다. 렌더링 중에 setTimeout을 호출 할 수 없기 때문에 서버 측 시간 초과가 발생합니다. – dhilt

+0

타임 아웃의 의미는 무엇입니까? 그게 뭐야? ssr을 사용할 때 이미 모든 데이터를 가지고 있다면 전체 페이지를 빌드 할 때까지 기다릴 필요가 없습니다. 타임 아웃의 목적은 내가 추측하는 데 도움이 될 것입니다. –

답변

0

일부 연구를 통해 다음과 같은 접근 방식을 적용 할 수있었습니다. utils/misc.js는 다음과 같은 개체를 가지고

import { _postRender } from '../utils/misc'; 

const doLockSideUI = (dispatch, lockObject) => { 
    // the body of previous version of doLockSide inner function 
    const timerId = setTimeout(() => {/*...*/}, lockObject.unlockTimeout); 
    dispatch(/*...*/); 
}; 

export const doLockSide = (lockObject) => (dispatch) => { 
    if(typeof window === 'undefined') { // server-side rendering case 
    _postRender.actions.push({ 
     name: 'doLockSide', 
     params: lockObject 
    }); 
    } 
    else { // Browser case 
    doLockSideUI(dispatch, lockObject); 
    } 
}; 

:

1) 브라우저의 경우 "있는 그대로"서버 측 렌더링의 경우에는 특별한 기억으로 이연 액션 데이터를 밀어하고 실행 : _postRender 개체 양식 utils/misc.js하고로 밀어 것을 내가 가져온 서버에서

// to run actions on the Client after server-side rendering 
export const _postRender = { actions: [] }; 

2) 모든 REDUX-데이터를 저장 종속성가 해결되었다개 매개 변수 :

const markup = renderToString(/*...*/); 
const finalState = store.getState(); 
const params = { markup, finalState, postRender: { ..._postRender } }; 
_postRender.actions = []; // need to reset post-render actions 
return res.status(status).render('index', params); 

_postRender.actions 다시 클라이언트가 다시로드했다 때마다 다른 P.1에서 _postRender.actions.push 다시 채 웁니다, 청소 및되어야한다.

3) 그런 다음 렌더링 후 작업은 미리로드 된 상태와 동일한 방식으로 제공됩니다.

<div id="main"><%- markup %></div> 
<script> 
    var __PRELOADED_STATE__ = <%- JSON.stringify(finalState) %>; 
    var __POST_RENDER__ = <%- JSON.stringify(postRender) %>; 
</script> 

4)가 지금은 주어진 PARAMS 내 __POST_RENDER__ 작업을 호출해야합니다 : 내 경우는 index.ejs 템플릿입니다.

import { doLockSide } from './topic' 

export const runAfterRender = (list) => (dispatch) => { 
    list.forEach(action => { 
    if(action.name === 'doLockSide') { 
     dispatch(doLockSide(action.params)); 
    } 
    // other actions? 
    }); 
}; 
: runAfterRender../actions/render에서 수입되는 새로운 액션이다

componentDidMount() { 
    console.log('The App has been run successfully'); 
    if(window.__POST_RENDER__ && window.__POST_RENDER__.actions.length) { 
    this.props.dispatch(runAfterRender(window.__POST_RENDER__.actions)); 
    } 
} 

:이 목적을 위해 내가 후크를 장착 않았고, 이후 렌더링 작업 목록을 처리하는 추가 작업을 파견 내 루트 구성 요소의 업데이트

알다시피 초안 일 뿐이므로 p13의 doLockSide 동작을 가져 와서 명시 적으로 호출해야했습니다. 서버 측 렌더링 후에 클라이언트에서 호출 할 수있는 가능한 동작 목록이있을 수 있지만이 방법은 이미 작동합니다. 더 나은 방법이 있는지 궁금합니다 ...