React 在 TS 中使用 Redux
这里我选择了使用 react-redux,redux-thunk,redux
除了上面这 3 个还需要在安装一个
(1)安装包依赖
cnpm install @types/react-redux
cnpm i redux
cnpm i react-redux
cnpm i redux-thunk
(2) (特别重要) 修改 react-app-env.d.ts
- 在 src 目录下面有一个文件 react-app-env.d.ts
修改这个文件的代码
/// <reference types="react-scripts" />
// 修改ReduxTools工具
interface Window extends REDUXTOOS {
__REDUX_DEVTOOLS_EXTENSION_COMPOSE__:
| string
| __REDUX_DEVTOOLS_EXTENSION_COMPOSE__;
}
declare var window: Window
(3) 在 src 目录下新建一个 store 文件夹,然后接着创建下面几个文件
actiontypes.tsx
actioncreaters.tsx
reducers.tsx
store.tsx
(i) actiontype.tsx
- 规定 action 的名字
export const ADD = 'ADD'
export const DELETE = 'DELETE'
export const CHANGE_VALUE = 'CHANGE_VALUE'
(ii) actioncreaters.tsx
- 创建 action
引入名字 然后定义返回值类型,最后暴露出去方法和方法类型,方法类型这里因为一样所以我用了或写法 也可以拆分
import { ADD, DELETE, CHANGE_VALUE } from './actiontypes'
//定义返回类型
interface ADD_RESULT {
type: string
}
interface DELETE_RESULT {
type: string
value: number
}
interface CHANGE_VALUE_RESULT {
type: string
value: string
}
//定义方法
export const add_action = (): ADD_RESULT => {
return {
type: ADD,
}
}
export const delete_action = (value: number): DELETE_RESULT => {
return {
type: DELETE,
value: value,
}
}
export const change_action = (value: string): CHANGE_VALUE_RESULT => {
return {
type: CHANGE_VALUE,
value: value,
}
}
(iii) reducers.tsx
写获取到数据后的处理方法
定义数据类型(也可以暴露出去)
绑定 action 数据类型
最后暴露类型
import { ADD, DELETE, CHANGE_VALUE } from './actiontypes'
//定义数据
export interface StateResult {
value: string
list: (string | number)[]
}
const defaultResult: StateResult = {
value: '',
list: [],
}
export default (state = defaultResult, action: any): StateResult => {
switch (action.type) {
case ADD:
let newresult = JSON.parse(JSON.stringify(state))
newresult.list.push(state.value)
newresult.value = ''
return newresult
case DELETE:
let newresult2 = JSON.parse(JSON.stringify(state))
newresult2.list.splice(action.value, 1)
return newresult2
case CHANGE_VALUE:
let newresult3 = JSON.parse(JSON.stringify(state))
newresult3.value = action.value
return newresult3
default:
return state
}
}
(iiii) store.tsx
- 因为用了第二步所以他不会报错误
import { createStore, compose, applyMiddleware } from 'redux'
import reducer from './reducers'
import thunk from 'redux-thunk'
const composeEnhancers =
typeof window === 'object' && window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
? window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__({
// Specify extension’s options like name, actionsBlacklist, actionsCreators, serialize...
})
: compose
const enhancer = composeEnhancers(applyMiddleware(thunk))
const store = createStore(reducer, enhancer)
export default store
(4) 组件里面使用
- 必须继承 RouteComponentProps 否则一定会报错
import * as React from 'react'
import { withRouter, Link, RouteComponentProps } from 'react-router-dom'
import { connect } from 'react-redux'
import { StateResult } from '../../store/reducers'
import {
add_action,
delete_action,
change_action,
} from '../../store/actioncreaters'
interface IHomeProps extends RouteComponentProps {
value: string
list: (string | number)[]
handleAdd: () => void
handleDel: (value: number) => void
handleChange: (value: any) => void
}
const Home: React.FunctionComponent<IHomeProps> = (props) => {
const { value, list, handleAdd, handleChange, handleDel } = props
return (
<div>
<span>这就是首页 </span>
<input type="text" onChange={handleChange} value={value}></input>
<button onClick={handleAdd}>增加</button>
<ul>
{list.map((item, index) => {
return (
<li
key={index}
onClick={() => {
handleDel(index)
}}
>
{' '}
{item}
</li>
)
})}
</ul>
<Link to="/second">点击跳转</Link>
</div>
)
}
const mapStateToProps = (state: StateResult) => {
return {
value: state.value,
list: state.list,
}
}
const mapDispatchToProps = (dispatch: any) => {
return {
handleAdd() {
dispatch(add_action())
},
handleDel(value: number) {
dispatch(delete_action(value))
},
handleChange(e: any) {
let result = e.target.value
dispatch(change_action(result))
},
}
}
export default connect(mapStateToProps, mapDispatchToProps)(withRouter(Home))
(5) index.tsx 里面代码 引入 store
import React from 'react'
import ReactDOM from 'react-dom'
import './reset.css'
import RouterComponent from './router'
import { Provider } from 'react-redux'
import store from './store/store'
ReactDOM.render(
<Provider store={store}>
<RouterComponent />
</Provider>,
document.getElementById('root')
)