<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                # 配置 Store 在[基礎](../basics/README.md)這一章節我們構建了一個 Todo list 應用,介紹了一些 Redux 基礎知識。 接下來我們將會探索如何定制 store 來添加額外的功能。我們將會接著基礎部分的源代碼繼續寫,你可以在[文檔](../basics/ExampleTodoList.md),或 [倉庫中的示例部分](https://github.com/reduxjs/redux/tree/master/examples/todos/src),或者用 [CodeSandbox 在瀏覽器中](https://codesandbox.io/s/github/reduxjs/redux/tree/master/examples/todos)閱讀這些代碼。 ## 創建 store 首先我們來看看在原先的 `index.js` 中我們是如何創建 store 的: ```js import React from 'react' import { render } from 'react-dom' import { Provider } from 'react-redux' import { createStore } from 'redux' import rootReducer from './reducers' import App from './components/App' const store = createStore(rootReducer) render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') ) ``` 代碼中,我們將 reducer 傳入 Redux 提供的 `createStore` 函數中,它返回了一個 `store` 對象。接著我們將這個對象傳入 `react-redux` 提供的 `Provider` 組件中,然后將它掛載在組件樹的根部。 這樣做可以保證我們在任何時候通過 `react-redux` 的 `connect` 連接到 Redux 時,store 可以在組件中正常使用。 ## 拓展 Redux 功能 大多數的應用都會使用 middleware 或 enhancer 來拓展 Redux store 的功能。**(注:middleware 很常見,enhancer 不太常見)** middleware 拓展了 Redux `dispatch` 函數的功能;enhancer 拓展了 Redux store 的功能。 我們將會添加如下兩個 middleware 和 一個 enhancer: - [`redux-thunk` middleware](https://github.com/reduxjs/redux-thunk),允許了簡單的 dispatch 異步用法。 - 一個記錄 dispatch 的 action 和得到的新 state 的 middleware。 - 一個記錄 reducer 處理每個 action 所用時間的 enhancer。 #### 安裝 `redux-thunk` ``` npm install --save redux-thunk ``` #### middleware/logger.js ```js const logger = store => next => action => { console.group(action.type) console.info('dispatching', action) let result = next(action) console.log('next state', store.getState()) console.groupEnd() return result } export default logger ``` #### enhancers/monitorReducer.js ```js const round = number => Math.round(number * 100) / 100 const monitorReducerEnhancer = createStore => ( reducer, initialState, enhancer ) => { const monitoredReducer = (state, action) => { const start = performance.now() const newState = reducer(state, action) const end = performance.now() const diff = round(end - start) console.log('reducer process time:', diff) return newState } return createStore(monitoredReducer, initialState, enhancer) } export default monitorReducerEnhancer ``` 我們把這些東西添加到 `index.js` 中。 - 首先我們引入 `redux-thunk`,我們自己寫的 `loggerMiddleware` 和 `monitorReducerEnhancer`,還有兩個 Redux 提供的函數:`applyMiddleware` 和 `compose`。 - 接下來我們用 `applyMiddleware` 來創建一個 store enhancer,通過它我們可以將 `loggerMiddleware` 和 `thunkMiddleware` 應用到 dispatch 函數。 - 下一步,我們使用 `compose` 將新的 `middlewareEnhancer` 和 `monitorReducerEnhancer` 組合到一起。這一步必須要做,因為 `createStore` 只接受一個 enhancer 作為參數,所以你只能將它倆組合(compose)成一個大的 enhancer,正如示例中所示。 - 最后,我們將這個 `composedEnhancers` 函數傳入 `createStore` 中作為第三個參數。 **注:這里我們忽略掉了 createStore 的第二個參數,你可以通過它給 store 傳入一個初始 state。** ```js import React from 'react' import { render } from 'react-dom' import { Provider } from 'react-redux' import { applyMiddleware, createStore, compose } from 'redux' import thunkMiddleware from 'redux-thunk' import rootReducer from './reducers' import loggerMiddleware from './middleware/logger' import monitorReducerEnhancer from './enhancers/monitorReducer' import App from './components/App' const middlewareEnhancer = applyMiddleware(loggerMiddleware, thunkMiddleware) const composedEnhancers = compose( middlewareEnhancer, monitorReducerEnhancer ) const store = createStore(rootReducer, undefined, composedEnhancers) render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') ) ``` ## 這種做法的問題 這些代碼的確能正常運行,但對于一個典型(typical)的應用來說還不夠理想。 大多數應用使用的 middleware 大于一個,而且每個 middleware 經常需要一些額外的初始化工作。這些“噪聲”的加入會使 `index.js` 很快變得難以維護,因為這些邏輯并沒有被清晰合理地組織起來。 ## 解決方案:`configureStore` 這個問題的解決方案是創造一個封裝了 store 創建邏輯的新的函數 `configureStore`。它放在一個單獨的文件中,所以可以被任意拓展。 我們的 `index.js` 的終極目標會是這樣: ```js import React from 'react' import { render } from 'react-dom' import { Provider } from 'react-redux' import App from './components/App' import configureStore from './configureStore' const store = configureStore() render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') ) ``` 所有配置 store 相關的邏輯(包括引入 reducer、middleware、enhancer),都放置于一個單獨用于處理它們的文件中。 為了達到這個目標,`configureStore` 函數應該是這樣: ```js import { applyMiddleware, compose, createStore } from 'redux' import thunkMiddleware from 'redux-thunk' import monitorReducersEnhancer from './enhancers/monitorReducers' import loggerMiddleware from './middleware/logger' import rootReducer from './reducers' export default function configureStore(preloadedState) { const middlewares = [loggerMiddleware, thunkMiddleware] const middlewareEnhancer = applyMiddleware(...middlewares) const enhancers = [middlewareEnhancer, monitorReducersEnhancer] const composedEnhancers = compose(...enhancers) const store = createStore(rootReducer, preloadedState, composedEnhancers) return store } ``` 這個函數遵循了上述步驟,其中有一些邏輯拆分開來,為后續拓展做好準備。 - `middlwares` 和 `enhancers` 都被定義為數組,與實際使用它們的函數分離開來。這樣做我們可以很容易地為不同情況添加更多的 middleware 或 enhancer。 例如,一種很常見的情況是,只有在開發模式下才添加某些 middleware。這個可以在一個 if 條件句中向 middleware 數組添加新的 middleware 來輕松實現: ```js if (process.env === 'development') { middlewares.push(secretMiddleware) } ``` - 將一個 `preloadedState` 變量傳入 `createStore`,以便后續使用。 這樣我們調試 `createStore` 也更輕松了——每個步驟都分離的清清楚楚,目前正在發生什么一目了然。 ## 集成 devtools 擴展程序 另外一個你很想在你的應用中加入的功能就是 `redux-devtools-extension` 的集成。 這個擴展程序是一系列工具的集合,通過它們你可以獲得 Redux store 完全的控制:它允許你觀察或重放 action,在不同時刻查看 state,直接向 store 中 dispatch 一個 action,......等等很多功能。[點擊此處閱讀更多](https://github.com/zalmoxisus/redux-devtools-extension)。 有很多方案可以集成此擴展程序,但我們會用最方便的那個。 首先,使用 npm 安裝: ``` npm install --save-dev redux-devtools-extension ``` 接下來,我們移除掉從 `redux` 引入的 `compose` 函數,然后用一個從 `redux-devtools-extension` 中引入的 `composeWithDevTools` 函數來替換它。 最終的代碼是這樣: ```js import { applyMiddleware, createStore } from 'redux' import thunkMiddleware from 'redux-thunk' import { composeWithDevTools } from 'redux-devtools-extension' import monitorReducersEnhancer from './enhancers/monitorReducers' import loggerMiddleware from './middleware/logger' import rootReducer from './reducers' export default function configureStore(preloadedState) { const middlewares = [loggerMiddleware, thunkMiddleware] const middlewareEnhancer = applyMiddleware(...middlewares) const enhancers = [middlewareEnhancer, monitorReducersEnhancer] const composedEnhancers = composeWithDevTools(...enhancers) const store = createStore(rootReducer, preloadedState, composedEnhancers) return store } ``` 這樣就成了! 現在用安裝了 devtools 擴展程序的瀏覽器訪問我們的應用,我們即可使用這一強大的工具來探索和調試了。 ## 熱加載 還有一個強大的工具可以使你的開發過程更加直觀,那就是熱加載(hot reloading),它可以在無需重啟整個應用的情況下替換代碼。 比如說,你啟動了應用程序,使用了一會兒,決定對其中一個 reducer 做一些改動。正常情況下,你做了改動后應用會重啟,并且 Redux state 會重置到其初始狀態。 當使用熱加載時,只有你做了更改的 reducer 會被重啟。這樣一來你就無需在每次修改代碼之后重置整個 state,開發過程會更加迅速。 我們將 Redux reducer 和 React 組件都啟用熱加載。 首先,將它引入 `configureStore` 函數: ```js import { applyMiddleware, compose, createStore } from 'redux' import thunkMiddleware from 'redux-thunk' import monitorReducersEnhancer from './enhancers/monitorReducers' import loggerMiddleware from './middleware/logger' import rootReducer from './reducers' export default function configureStore(preloadedState) { const middlewares = [loggerMiddleware, thunkMiddleware] const middlewareEnhancer = applyMiddleware(...middlewares) const enhancers = [middlewareEnhancer, monitorReducersEnhancer] const composedEnhancers = compose(...enhancers) const store = createStore(rootReducer, preloadedState, composedEnhancers) if (process.env.NODE_ENV !== 'production' && module.hot) { module.hot.accept('./reducers', () => store.replaceReducer(rootReducer)) } return store } ``` 新的代碼放置在 `if` 條件句中,所以它只在非生產環境中運行,而且只在能用 `module.hot` 時運行。 像 Webpack 和 Parcel 這樣的打包工具支持 `module.hot.accept` 方法,它用于指定哪一個模塊(module)應該啟用熱加載,以及當模塊改變時應該做什么。此例中,我們監控 `./reducers` 模塊,當這個模塊改變時將新計算出的 `rootReducer` 傳入 `store.replaceReducer` 函數。 在 `index.js` 中,我們也會使用相同的模式來熱加載 React 組件: ```js import React from 'react' import { render } from 'react-dom' import { Provider } from 'react-redux' import App from './components/App' import configureStore from './configureStore' const store = configureStore() const renderApp = () => render( <Provider store={store}> <App /> </Provider>, document.getElementById('root') ) if (process.env.NODE_ENV !== 'production' && module.hot) { module.hot.accept('./components/App', renderApp) } renderApp() ``` 這里只有一個地方與剛剛不同,就是我們將應用的渲染封裝進了 `renderApp` 函數,調用它將會重新渲染整個應用。 ## 下一步 現在你已經學會了將配置 store 的方法進行封裝,讓它更易于維護。你現在可以[學習 Redux 提供的高級特性](../advanced/README.md),或者看看一些[Redux 生態系統提供的擴展程序](../introduction/Ecosystem.md#debuggers-and-viewers)。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看