ps: 最近在学react和redux。用了几天时间看了下,个人觉得react本身比较易懂,但是涉及到的各种中间件和api让人脑阔疼(正好前段时间用vue+koa写了个简易的博客,对中间件还算理解)。在看到redux的时候,被这个real world的栗子难住了(个人水平太low)还2天过年,心思也不在这了。本来想放弃了,后来想想年后就辞职找工作了(心芳芳)新的风暴已经出现,怎么能够停滞不前。硬着头皮看下代码吧!
栗子目录是酱紫的....,咱们剥洋葱(衣服)一样,慢慢深入。
根目录下的index.js ( Root模板,store数据和逻辑 )
import React from ‘react‘ import { render } from ‘react-dom‘ import { BrowserRouter as Router } from ‘react-router-dom‘ import Root from ‘./containers/Root‘ import configureStore from ‘./store/configureStore‘ const store = configureStore(); render( <Router> <Root store={store} /> // 由顶层传入store,谨记redux三大原则(单一store,store改变必须由dispatch来通知,reducer最好是pure函数
) </Router>, document.getElementById(‘root‘) );
/containers/Root ( 就2行代码,根据运行环境切换输出 )
if (process.env.NODE_ENV === ‘production‘) { module.exports = require(‘./Root.prod‘) } else { module.exports = require(‘./Root.dev‘) }
/containers/Root.dev.js
import React from ‘react‘ import PropTypes from ‘prop-types‘ // props类型检查 import { Provider } from ‘react-redux‘ // 包装函数,用于将redux和react链接起来 import DevTools from ‘./DevTools‘ // 可视化调试工具,用法简单 import { Route } from ‘react-router-dom‘ // 路由 import App from ‘./App‘ import UserPage from ‘./UserPage‘ import RepoPage from ‘./RepoPage‘ const Root = ({ store }) => ( <Provider store={store}> <div> <Route path="/" component={App} /> <Route path="/:login/:name" component={RepoPage} /> <Route path="/:login" component={UserPage} /> <DevTools /> </div> </Provider> ) Root.propTypes = { store: PropTypes.object.isRequired, } export default Root
/containers/APP.js ( 顶层逻辑,react是单向数据流,由高流向低( 父->子->孙 ) )
import React, { Component } from ‘react‘
import PropTypes from ‘prop-types‘
import { connect } from ‘react-redux‘
import { withRouter } from ‘react-router-dom‘
import Explore from ‘../components/Explore‘
import { resetErrorMessage } from ‘../actions‘
class App extends Component {
static propTypes = {
// Injected by React Redux
errorMessage: PropTypes.string,
resetErrorMessage: PropTypes.func.isRequired,
inputValue: PropTypes.string.isRequired,
// Injected by React Router
children: PropTypes.node // 由路由注入?怎么个注入法?
};
handleDismissClick = e => {
this.props.resetErrorMessage();
e.preventDefault()
};
handleChange = nextValue => {
this.props.history.push(`/${nextValue}`)
};
renderErrorMessage() {
const { errorMessage } = this.props;
if (!errorMessage) {
return null
}
return (
<p style={{ backgroundColor: ‘#e99‘, padding: 10 }}>
<b>{errorMessage}</b>
{‘ ‘}
<button onClick={this.handleDismissClick}>
Dismiss
</button>
</p>
)
}
render() {
const { children, inputValue } = this.props;
return (
<div>
<Explore value={inputValue}
onChange={this.handleChange} />
<hr />
{this.renderErrorMessage()}
{children}
</div>
)
}
}
const mapStateToProps = (state, ownProps) => ({ // 订阅Store,每当state变化时就会重新渲染。第一个参数是Store,第二个参数是当前组件的props对象,props改变也会重新渲染
errorMessage: state.errorMessage,
inputValue: ownProps.location.pathname.substring(1) // 必须要ownProps.location.pathname才能拿到path吗,反正path变化会触发渲染,类似Vue的watch router
});
export default withRouter(connect(mapStateToProps, { // withRouter可以包装任何自定义组件,无需一级级传递react-router属性,就可以拿到需要的路由信息
resetErrorMessage
})(App)