react项目使用redux入门-1
redux
redux使用步骤
使用步骤:
- 定义一个 reducer 函数 (根据当前想要做的修改返回一个新的状态)
- 使用createStore方法传入 reducer函数 生成一个store实例对象
- 使用store实例的 subscribe方法 订阅数据的变化(数据一旦变化,可以得到通知)
- 使用store实例的 dispatch方法提交action对象 触发数据变化(告诉reducer你想怎么改数据)
- 使用store实例的 getState方法 获取最新的状态数据更新到视图中
实现计数器
需求:不和任何框架绑定,不使用任何构建工具,使用纯Redux实现计数器
代码实现:
<button id="decrement">-</button>
<span id="count">0</span>
<button id="increment">+</button>
<script src="https://unpkg.com/redux@latest/dist/redux.min.js"></script>
<script>
// 定义reducer函数
// 内部主要的工作是根据不同的action 返回不同的state
function counterReducer (state = { count: 0 }, action) {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + 1 }
case 'DECREMENT':
return { count: state.count - 1 }
default:
return state
}
}
// 使用reducer函数生成store实例
const store = Redux.createStore(counterReducer)
// 订阅数据变化
store.subscribe(() => {
console.log(store.getState())
document.getElementById('count').innerText = store.getState().count
})
// 增
const inBtn = document.getElementById('increment')
inBtn.addEventListener('click', () => {
store.dispatch({
type: 'INCREMENT'
})
})
// 减
const dBtn = document.getElementById('decrement')
dBtn.addEventListener('click', () => {
store.dispatch({
type: 'DECREMENT'
})
})
</script>
场景:切换语言
-
安装
redux
依赖包npm i redux --save
-
在根目录(src)下新建目录
redux
及文件mkdir src/redux touch src/redux/store.ts touch src/redux/languageReducer.ts
store.ts
import { createStore } from 'redux' import languageReducer form './languageReducer.ts' const store = createStore(languageReducer) export default store
languageReducer.ts
interface LanguageState { lng: 'zh' | 'en', languageList: {code: string, language: string}[] } export interface LanguageAction { type: 'language/change' | 'language/add', payload: any } const defaultStoreState: LanguageState = { lng: 'zh', languageList: [{ code: 'zh', language: '中文'}, { code: 'en', language: 'English'}] } export default (state = defaultStoreState, action: LanguageAction) => { switch(action.type){ case: 'language/change': return {...state, lng: action.payload} case: 'language/add': return { ...state, languageList: [state.languageList, payload]} default: return state } }
-
Header
组件中使用store
import { Component } from 'react' import { withRouter, RouteComponentProps } from 'react-router-dom' import { MenuInfo } from 'rc-menu/lib/interface' import { nanoid } from 'nanoid' import store from 'redux/store' import { LanguageState, LanguageAction } from 'redux/languageAction' const interface StateProps extends LangageState {} class HeaderComponent extends Component<RouteComponentProps, StateProps>{ constructor(props:RouteComponentProps){ super(props) /* state初始化获取 store中的数据 */ const storeState = store.getState() this.state = { lng: storeState.lng, languageList: storeState.languageList } } componentDidMount(){ /* subscribe */ store.subscribe(() => { const storeState = store.getState() this.setState({ lng: storeState.lng, languageList: storeState.languageList }) }) } render(){ /* meun 的点击事件 */ const oprateLanguage = ( e: MenuInfo ) => { let action if(e.key !== 'new'){ action = { type: 'language/change', payload: e.key } }else{ action = { type: 'language/add', payload: { code: `lng${nanoid()}`, language: '新语种'} } } /* dispatch */ store.dispatch<LanguageAction>(action) } const menu = ( <Menu> <Menu.Item key='new' onClick={oprateLanguage}> 添加新语言 </Menu.Item> {languageList.map(language => ( <Menu.Item key={language.code} onClick={oprateLanguage}> {language.language} </Menu.Item> ))} </Menu> ) return ( <div> <Typography.Text className='mr40'>让旅游更幸福</Typography.Text> <Dropdown overlay={menu}> <Button> {languageList.find(language => language.code === lng)?.language} <GlobalOutlined /> </Button> </Dropdown> <Button.Group> <Button onClick={() => history.push('/signIn')}>登录</Button> <Button onClick={() => history.push('/register')}>注册</Button> </Button.Group> </div> ) } } export const Header = withRouter(HeaderComponent)