iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 7
0

前言

我找到一篇 Redux 的初學教學,是一個外國人寫的,我順便翻寫他所做的文章,也方便我釐清觀念。

Getting started with create-react-app, Redux, React Router & Redux Thunk

1.create-react-app

首先用create-react-app 建立環境

create-react-app react-redux-example
cd react-redux-example

安裝套件

yarn add redux react-redux react-router-dom react-router-redux@next redux-thunk history

redux,react-redux,react-router-dom 不多解釋,react-router-redux,主要是讓react-router-dom的components 也納入redux 的方式管理, redux-thunk是處理非同步問題(如串api)

react-router-redux 介紹
redux-thunk

#/src 一切檔案都建立在/src裡面

程式

1. Store

這邊是設定react-routerredux-thunkstore,引入redux的core去創造一個custom的全域store
react-router-reduxredux-thunk是redux的中介層(middleware),一個概念,全都交給redux

// 稍後會再加進reducer,

You’ll notice we’re importing a file we haven’t yet created called rootReducer. This is essential to Redux. We’ll come back to Reducers later but for now, create a file called ./src/modules/index.js so we can satisfy our Store.

redux

createStorecomposeapplyMiddleware

1.createStrore 建立一個 Redux store,它掌控應用程式的完整 state tree。 在你的應用程式中應該只有單一一個 store。
2.compose:把 function 從右到左組合起來。
3.applyMiddleware:建立一個Middleware

Store觀念

react-router-redux

1.routerMiddleware(history):你可以用到你的Redux Store中来取得action creator創建的acion。它會將這些操作重定向到提供的history實例。

react-thunk

thunk

history

HTML5的history API

import { createStore, applyMiddleware, compose } from 'redux'
import { routerMiddleware } from 'react-router-redux'
import thunk from 'redux-thunk'
import createHistory from 'history/createBrowserHistory'
import rootReducer from './modules'

export const history = createHistory()

const initialState = {}
const enhancers = []
const middleware = [
  thunk,
  routerMiddleware(history)
]// 這邊把thunk跟history資料串起來

// 這段是偵測是否為開發模式
if (process.env.NODE_ENV === 'development') {
  const devToolsExtension = window.devToolsExtension

  if (typeof devToolsExtension === 'function') {
    enhancers.push(devToolsExtension())
  }
}

// 將function 組合起來
const composedEnhancers = compose(
  applyMiddleware(...middleware),
  ...enhancers
)

const store = createStore(
  rootReducer,
  initialState,
  composedEnhancers
)

export default store

./src/modules/index.js

redux

1.combineReducers : 把reducing funcion 的物件轉換成一個可以傳給createStore的單一reducin funtion

react-router-redux

1.routerReducer:同[reducer](https://chentsulin.github.io/redux/docs/basics/Reducers.html) 觀念,儲存router的資料,他會傳給剛剛的./store
import { combineReducers } from 'redux'
import { routerReducer } from 'react-router-redux'

export default combineReducers({
  routing: routerReducer
})

Routes

這邊說明,components 會放到container coponents App裡面。

Our router history is managed inside our Redux store which we created in the first section and is passed down via something called ConnectedRouter which we will implement later.

Containers App

容器Containers,redux觀念裡,需要控制資料流的components 都會叫容器,也可以說是一個版,整個頁面都是包在App內執行,

import React from 'react';
import { Route, Link } from 'react-router-dom'
import Home from '../home'
import About from '../about'

const App = () => (
  <div>
    <header>
      <Link to="/">Home</Link>
      <Link to="/about-us">About</Link>
    </header>

    <main>
      <Route exact path="/" component={Home} />
      <Route exact path="/about-us" component={About} />
    </main>
  </div>
)

Home.js

刻出/home的分頁

redux

1.bindActionCreators:

react-redux

1.connect:使用 connect() function 來產生 container component,它提供了許多有用的最佳化來避免不必要的重新 render。

redux

1.bindActionCretors:把一個每個值都是 action creator 的物件轉換成另一個有同樣的 keys 的物件,不過每個 action creator 都被包進一個 dispatch 呼叫裡面,所以它們可以直接被呼叫。
bindActionCreators 唯一的使用情境是,當你希望傳遞一些 action creator 下去一個不知道 Redux 存在的 component,而你不希望把 dispatch 或是 Redux 的 store 傳遞給它。

reacr-router-redux

1.push:看他作用應該跟history.push()是一樣觀念

import React from 'react'
import { push } from 'react-router-redux'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'

const Home = props => (
  <div>
    <h1>Home</h1>
    <p>Welcome home!</p>
    <button onClick={() => props.changePage()}>Go to about page via redux</button>
  </div>
)

const mapDispatchToProps = dispatch => bindActionCreators({
  changePage: () => push('/about-us')
}, dispatch)

export default connect(
  null, 
  mapDispatchToProps
)(Home)

about.js

import React from 'react'

export default () => (
  <div>
    <h1>About Us</h1>
    <p>Hello Medium!</p>
  </div>
)

Rendering our app

明天待續


上一篇
Redux 與 React 結合
下一篇
React-Redux-框架練習(2)
系列文
初探前端之路-React-由生到死的踩地雷10

尚未有邦友留言

立即登入留言