簡體   English   中英

使用redux進行服務器端渲染

[英]Server side rendering with redux

我有一個使用reactjs和redux構建的簡單應用程序。 由於我剛剛開始學習redux,我在服務器端渲染時遇到了一些問題。

到目前為止我所擁有的是... Client App.js渲染App組件。

render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.body
);

一個App組件:

const App = () => (
  <div>
    <SearchContainer />
    <TodoContainer />
  </div>
)

如果兩個項都是容器,則SearchContainer從輸入框獲取輸入,觸發一個動作,該動作將使用加載的todo`s(來自遠程休息服務)調度消息。

現在我喜歡在服務器端的頁面加載上加載那些todo,並在頁面顯示后顯示它們。 我該怎么辦? 有沒有辦法在頁面實際顯示之前不使用服務器端渲染和加載項目?

到目前為止,我到目前為止是routes.js文件:

  const middleware = [ thunk ]
  if (process.env.NODE_ENV !== 'production') {
    middleware.push(createLogger())
  }

  const store = createStore(reducer,applyMiddleware(...middleware))

  app.get('/', function(req, res) {
    res.render('home',{
      markup: ReactDOMServer.renderToString(
        <Provider store={store}>
          <App />
        </Provider>
      )
    });
//Some code calling remote service goes here

這通常是加載和應用程序,但我如何將加載的數據推送到TodoContainer? 它應該是某種方式來分派消息,還是應該使用todos數組作為屬性來初始化App組件?

您不需要服務器端渲染。

解決您遇到的問題的最常見方法是從componentDidMount加載數據。 在返回此數據之前,您需要顯示某些內容,例如微調器或笨蛋或消息​​或空白頁。 就是那樣子。 您的應用不會是唯一一個帶有加載指示器的應用...

不過,你也可以做的,就是獲取數據的服務器端,你發送的頁面下來之前,和頁面的送下來<script>標記和幫助JSON.stringify

<script>
  window.initialData = {
    "myData": [ 1, 2, 3 ]
  };
</script>

然后你可以用它來初始化商店。 這使數據立即可用,並消除了對API端點的需求。

const store = createStore(reducer, window.initialData, applyMiddleware(...middleware));

您也可以使用相同的數據在服務器上進行渲染,但無論如何都不需要它。

最后,我想指出你正在渲染document.body ,這是一個壞主意,因為很多瀏覽器擴展和插件為了自己的需要在DOM中添加了div或其他東西。 React不適合那些。 它期望控制它傳遞的元素。 最好只創建一個div並將其渲染成一個div

考慮一下你是否真的需要在todo app中使用SSR。 主要優點是改進了SEO,你的應用程序准備好了一點(它已經渲染)。 如果它不會很重,你可能想跳過它。

有沒有辦法在頁面實際顯示之前不使用服務器端渲染和加載項目?

是的,例如,您可以調度獲取數據的操作並將其推送到componentWillMount Redux狀態。 在數據不存在之前,您可以渲染某些加載指示器的null

好吧,我已經獲得了一些反應,redux,nodejs和其他一些客戶端和服務器端技術的經驗,這是我發現的以及它如何為我工作。

react / redux應用程序中的服務器端呈現包括以下幾個步驟:1。在服務器上加載數據2.將數據從服務器推送到客戶端3.將數據加載到redux存儲

這是一個上傳'redux-polyglot'組件翻譯的小例子。

routes.js [處理快速服務器請求]:

//...all of your imports goes here
import en_phrases from './resources/phrases/en'

app.get('/', async function(req, res) {

    const store = createStore(reducers, applyMiddleware(...whatevermiddlewareyouneed))
    return res.render('home', {
            markup:  ReactDOMServer.renderToString(
              <Provider store={store}>
                <App/>
              </Provider>
            ),
            otherPreloadedStateThanPhrases: JSON.stringify(...anythingelse)
            phrases: JSON.stringify(en_phrases)
      });
}

這里的'home'值是把手模板名稱,它具有:

<script type="application/json" id="phrases">
  {{{ phrases }}}
</script>

然后,應用程序的職責是從“短語”腳本標記加載數據,並將其設置為具有多語言提供功能的默認語言。

app.js

const phrases = JSON.parse(document.getElementById('phrases').innerHTML);

const store = createStore(reducers, otherPreloadedStateThanPhrases, applyMiddleware(...middleware));
store.dispatch(setLanguage('en', phrases));

LoginContainer.js [從應用程序中使用的樣本容器]

let LoginContainer = ({p}) => {
     <span>{p.tc('login')}</span>
}
exports.LoginContainer = connect((state) => ()(translate(LoginContainer))

其中'login'是從服務器上的短語json加載的值:en.js

export default {
  login: "Login"
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM