簡介:簡單實現react-redux基礎api
react-redux api回顧
把store放在context里,所有子組件可以直接拿到store數據
使組件層級中的 connect() 方法都能夠獲得 Redux store 根組件應該嵌套在中
ReactDOM.render(, rootEl ) ReactDOM.render( , document.getElementById("root") )
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options])
鏈接組件和數據,把redux中的數據放到組件的屬性中
[mapStateToProps(state, [ownProps]): stateProps] (Function)
如果定義該參數,組件將會監聽 Redux store 的變化。任何時候,只要 Redux store 發生改變,mapStateToProps 函數就會被調用。該回調函數必須返回一個純對象,這個對象會與組件的 props 合并
如果你省略了這個參數,你的組件將不會監聽 Redux store
ownProps,則該參數的值為傳遞到組件的 props,而且只要組件接收到新的 props,mapStateToProps 也會被調用,被重新計算
mapStateToProps 函數的第一個參數是整個Redux store的state,它返回一個要作為 props 傳遞的對象。它通常被稱作 selector (選擇器)。 可以使用reselect去有效地組合選擇器和計算衍生數據.
注意:如果定義一個包含強制性參數函數(這個函數的長度為 1)時,ownProps 不會傳到 mapStateToProps
const mapStateToProps = (state, ownProps) => { return { active: ownProps.filter === state.visibilityFilter } }
[mapDispatchToProps(dispatch, [ownProps]): dispatchProps] (Object or Function)
Object: 它的每個鍵名也是對應 UI 組件的同名參數,鍵值應該是一個函數(action creator),會被當作 Action creator ,返回的 Action 會由 Redux 自動發出, Function: 會得到dispatch和ownProps(容器組件的props對象)兩個參數(此時可能用到Redux 的輔助函數 bindActionCreators())
省略這個 mapDispatchToProps 參數,默認情況下,dispatch 會注入到你的組件 props 中,你可以this.props.dispatch調用
指定了該回調函數中第二個參數 ownProps,該參數的值為傳遞到組件的 props,而且只要組件接收到新 props,mapDispatchToProps 也會被調用
eg:
connect(mapStateToProps, { hideAdPanel, pushAdData, })(AdPanel) function mapDispatchToProps(dispatch) { return { todoActions: bindActionCreators(todoActionCreators, dispatch), counterActions: bindActionCreators(counterActionCreators, dispatch) } }知識點補充 - React高階組件(Higher-Order Components)
高階組件就是一個函數,且該函數接受一個組件作為參數,并返回一個新的組件
高階組件就是一個沒有副作用的純函數
使用場景:兩個組件大部分代碼都是重復的+且更好的封閉性,不需要關注數據的獲取
import React, {Component} from "react" class Welcome extends Component { constructor(props) { super(props); this.state = { username: "" } } componentWillMount() { let username = localStorage.getItem("username"); this.setState({ username: username }) } render() { return (welcome {this.state.username}) } } export default Welcome; import React, {Component} from "react" class Goodbye extends Component { constructor(props) { super(props); this.state = { username: "" } } componentWillMount() { let username = localStorage.getItem("username"); this.setState({ username: username }) } render() { return (goodbye {this.state.username}) } } export default Goodbye;
welcome和goodbye組件相似,只能獲取的數據不一樣,用高階組件,提取公共部分
import React, {Component} from "react" export default (WrappedComponent) => { class NewComponent extends Component { constructor() { super(); this.state = { username: "" } } componentWillMount() { let username = localStorage.getItem("username"); this.setState({ username: username }) } render() { return} } return NewComponent } 簡化welcome和goodbye import React, {Component} from "react"; import wrapWithUsername from "wrapWithUsername"; class Welcome extends Component { render() { return ( welcome {this.props.username}) } } Welcome = wrapWithUsername(Welcome); export default Welcome;
此時,理解react-redux 的connect就好理解了
ConnectedComment = connect(mapStateToProps, mapDispatchToProps)(Component); // connect是一個返回函數的函數(就是個高階函數) const enhance = connect(mapStateToProps, mapDispatchToProps); // 返回的函數就是一個高階組件,該高階組件返回一個與Redux store // 關聯起來的新組件 const ConnectedComment = enhance(Component);provider實現
import React from "react" import ReactDOM from "react-dom" import { createStore, applyMiddleware, compose} from "redux" import thunk from "redux-thunk" import { counter } from "./index.redux" // import { Provider } from "react-redux" // 換成自己的Provider實現 import { Provider } from "./self-react-redux" import App from "./App" const store = createStore(counter, compose( applyMiddleware(thunk), window.devToolsExtension ? window.devToolsExtension() : f => f )) ReactDOM.render( (), document.getElementById("root"))
./self-react-redux
import React from "react" import PropTypes from "prop-types" export function connect(){ } class Provider extends React.Component{ static childContextTypes = { store: PropTypes.object } getChildContext() { return { store: this.store } } constructor(props, context) { super(props, context) this.store = props.store } render(){ return this.props.children } }connect實現
demo
import React from "react" // import { connect } from "react-redux" import { connect } from "./self-react-redux" import { addGun, removeGun, addGunAsync } from "./index.redux" @connect( // 你要state什么屬性放到props里 state=>({num:state.counter}), // 你要什么方法,放到props里,自動dispatch { addGun, removeGun, addGunAsync } ) class App extends React.Component{ render(){ return () } } export default App現在有機槍{this.props.num}把
./self-react-redux.js
// 高階組件的寫法 export function connect(maoStateToProps, mapStateToProps) { return function(WrapComponent) { return class ConnectComponent extends React.Component{ } } } import React from "react" import PropTypes from "prop-types" import { bindActionCreator } from "./self-redux" // 使用簡寫形式 // connect負責鏈接組件,給到redux里的數據放在組件的屬性里 // 1. 負責接收一個組件,把state里的一些數據放進去,返回一個組件 // 2. 數據變化的時候,能通知組件 export const connect = ( mapStateToProps = state => state, mapDispatchToProps ={} ) => (WrapComponent) => { return class ConnectComponent extends React.Component { static contextTypes = { store: PropTypes.object } constructor(props, context){ super(props, context) this.state = { props: {} } } // 2 實現了mapStateToProps componentDidMount() { const { store } = this.context store.subscribe(() => this.update()) this.update() } update() { const { store } = this.context // store.getState()這就是為什么mapStateToProps函數里面能拿到state const stateProps = mapStateToProps(store.getState()) // 方法不能直接給,因為需要dispatch /** function addGun() { return { type: ADD_GUN } } 直接執行addGun() 毫無意義 要 addGun = () => store.dispatch(addGun()) 才有意義,其實就是把actionCreator包了一層 bindActionCreators在手寫redux api實現了 */ const dispatchProps = bindActionCreators(mapDispatchToProps, store.dispatch) // 注意state的順序問題會覆蓋 this.setState({ props: { ...this.state.props, ...stateProps, ...dispatchProps, } }) } // 1 render() { return} } }
./self-redux.js
// creators: {addGun, removeGun, addGunAsync} // creators[v]:addGun(參數) // 返回:(參數) => dispatch(addGun(參數)) function bindActionCreator(creator, dispatch) { return (...args) => dispatch(creator(...args)) } export function bindActionCreators(creators, dispatch) { let bound = {} Object.keys(creators).forEach( v => { let creator = creators[v] bound[v] = bindActionCreator(creator, dispatch) }) return bound } // 簡寫 export function bindActionCreators(creators, dispatch) { return Object.keys(creators).reduce((ret, item) => { ret[item] = bindActionCreator(creators[item], dispatch) return ret }, {}) }
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/98563.html
摘要:每個接受的和函數作為命名參數,并返回一個函數。調用鏈中最后一個會接受真實的的方法作為參數,并借此結束調用鏈。 簡介: 手寫實現redux基礎api createStore( )和store相關方法 api回顧: createStore(reducer, [preloadedState], enhancer) 創建一個 Redux store 來以存放應用中所有的 state reduc...
摘要:的優勢保證不可變每次通過操作的對象都會返回一個新的對象豐富的性能好通過字典樹對數據結構的共享的問題與原生交互不友好通過生成的對象在操作上與原生不同,如訪問屬性,。 Immutable.js Immutable的優勢 1. 保證不可變(每次通過Immutable.js操作的對象都會返回一個新的對象) 2. 豐富的API 3. 性能好 (通過字典樹對數據結構的共享) Immutab...
摘要:前言是一個非常實用的狀態管理庫,對于大多數使用庫的開發者來說,都是會接觸到的。在使用享受其帶來的便利的同時,我們也深受其問題的困擾。只支持同步,讓狀態可預測,方便測試。粗暴地級聯式刷新視圖使用優化。 前言 Redux是一個非常實用的狀態管理庫,對于大多數使用React庫的開發者來說,Redux都是會接觸到的。在使用Redux享受其帶來的便利的同時, 我們也深受其問題的困擾。 redux...
摘要:前言前段時間學習完了的基礎自己網上找了一些實戰項目做了幾個感覺項目不是很全面就想做一個完整的項目來提升自己的水平以前學習的時候就看過大神的項目所以自己打算用重寫它后端數據還是用實在沒有精力擼后端感謝大神該項目是餓了么目前開發了登錄注冊購 前言 前段時間學習完了React的基礎,自己網上找了一些實戰項目,做了幾個感覺項目不是很全面,就想做一個完整的項目來提升自己的React水平.以前學習...
摘要:本文轉載至今日頭條技術博客眾所周知,的單向數據流模式導致狀態只能一級一級的由父組件傳遞到子組件,在大中型應用中較為繁瑣不好管理,通常我們需要使用來幫助我們進行管理,然而隨著的發布,新成為了新的選擇。 本文轉載至:今日頭條技術博客showImg(https://segmentfault.com/img/bVbiNJO?w=900&h=383);眾所周知,React的單向數據流模式導致狀態...
閱讀 3691·2021-11-19 09:56
閱讀 1473·2021-09-22 15:11
閱讀 1133·2019-08-30 15:55
閱讀 3379·2019-08-29 14:02
閱讀 2917·2019-08-29 11:07
閱讀 439·2019-08-28 17:52
閱讀 3175·2019-08-26 13:59
閱讀 442·2019-08-26 13:53