收集至:https://zhuanlan.zhihu.com/p/42141179
无状态组件
import * as React from "react";
const TestPage: React.SFC = () => {
return (
<div>
this is test page.
</div>
);
};
export default TestPage;
当我们需要传递 Props 时,只用定义一个 Props 接口,然后给 props 指明类型:
export interface IHeaderProps {
localImageSrc: string;
onLineImageSrc: string;
}
export const Header: React.SFC<IHeaderProps> = (props: IHeaderProps) => {
const { localImageSrc, onLineImageSrc } = props;
return (
<div className={styles["header-container"]}>
<img src={localImageSrc} />
<img src={onLineImageSrc} />
</div>
);
};
有状态组件
export interface IHomePageState {
name: string;
}
class HomeComponent extends React.Component<{}, IHomePageState> {
constructor(props: {}) {
super(props);
this.state = {
name: "",
};
}
public setName = () => {
this.setState({
name: "icepy",
});
}
public render(){
const { name } = this.state;
return (
<div>
<div onClick={this.setName}> set name </div>
<div>{name}</div>
</div>
)
}
}
Props & State 组件
export interface IHomePageState {
name: string;
}
export interface IHomePageProps {
home: string;
}
class HomeComponent extends React.Component<IHomePageProps, IHomePageState> {
constructor(props: IHomePageProps) {
super(props);
this.state = {
name: "",
};
}
public setName = () => {
this.setState({
name: "icepy",
});
}
public render(){
const { name } = this.state;
const { home } = this.props;
return (
<div>
<div onClick={this.setName}> set name </div>
<div>{name} {home}</div>
</div>
)
}
}
Router 组件
import { RouteComponentProps } from "react-router-dom";
export interface IHomePageProps extends RouteComponentProps<any>{
home: string;
}
export interface IHomePageState {
home: string;
}
class HomeComponent extends React.Component<IHomePageProps, IHomePageState> {
constructor(props: IHomePageProps) {
super(props);
this.state = {
name: "",
};
}
public setName = () => {
this.setState({
name: "icepy",
});
}
public render(){
const { name } = this.state;
const { home } = this.props;
return (
<div>
<div onClick={this.setName}> set name </div>
<div>{name} {home}</div>
</div>
)
}
}
页面级别的 Reducers
为类型安全定义接口:
import { Dispatch } from "redux";
import { RouteComponentProps } from "react-router-dom";
export interface IHomePageActionsProps {
dataSync: () => void;
dataAsync: (parameter: string) => (dispatch: Dispatch) => void;
}
export interface IHomePageProps extends RouteComponentProps<any>, IHomePageActionsProps {
homePage: IHomePageStoreState;
}
export interface IHomePageStoreState {
syncId: string;
asyncId: string;
}
// global dir
export interface IStoreState {
homePage: IHomePageStoreState;
}
定义一个 mapStateToProps 函数:
const mapStateToProps = (state: IStoreState) => {
const { homePage } = state;
return {
homePage,
};
};
定义 Action 和 Reducers:
// action
import * as CONST from "./constants";
import { Dispatch } from "redux";
export function dataSync() {
const syncData = {
type: CONST.SYNC_DATA,
payload: {
data: "syncId=https://github.com/icepy",
},
};
return syncData;
}
export function dataAsync(parameter: string): (dispatch: Dispatch) => void {
return (dispatch: Dispatch) => {
const asyncData = {
type: CONST.ASYNC_DATA,
payload: {
data: "asyncId=https://icepy.me",
},
};
setTimeout(() => {
dispatch(asyncData);
}, 2000);
};
}
// reducers
import { IAction } from "@/global/types";
import * as CONST from "./constants";
import * as TYPES from "./types";
const initState: TYPES.IHomePageStoreState = {
syncId: "默认值",
asyncId: "默认值",
};
export function homeReducers(state = initState, action: IAction): TYPES.IHomePageStoreState {
const { type, payload } = action;
switch (type) {
case CONST.SYNC_DATA:
return { ...state, syncId: payload.data };
case CONST.ASYNC_DATA:
return { ...state, asyncId: payload.data };
default:
return { ...state };
}
}
在 Store 中 引入我们的 reducers:
import { createStore, applyMiddleware, combineReducers, compose } from "redux";
import thunk from "redux-thunk";
import { homeReducers } from "@/pages/Home/flow/homeReducers";
/* eslint-disable no-underscore-dangle, no-undef */
const composeEnhancers = (window as any) && (window as any).REDUX_DEVTOOLS_EXTENSION_COMPOSE || compose;
const reducer = combineReducers({
homePage: homeReducers,
});
export const configureStore = () => createStore(
reducer,
composeEnhancers(applyMiddleware(thunk)),
);
使用 connect 函数将这些关联起来:
class HomeComponent extends React.Component<TYPES.IHomePageProps, TYPES.IHomePageState> {
... 省略
}
export const HomePage = connect(mapStateToProps, actions)(HomeComponent);
Global级别的 Reducers
global 顾名思义,这是一种可以全局访问的 reducers ,我们要做的事情也和页面级别 reducers 非常类似,定义好 state 的接口,然后将 global 在 Store 中配置正确,如:
import { createStore, applyMiddleware, combineReducers, compose } from "redux";
import thunk from "redux-thunk";
import { homeReducers } from "@/pages/Home/flow/homeReducers";
import { globalReducers } from "./reducers";
const composeEnhancers = (window as any) && (window as any).REDUX_DEVTOOLS_EXTENSION_COMPOSE || compose;
const reducer = combineReducers({
global: globalReducers,
homePage: homeReducers,
});
export const configureStore = () => createStore(
reducer,
composeEnhancers(applyMiddleware(thunk)),
);
当我们需要访问 global 时,有两种方式:
在 mapStateToProps 函数中将 global 返回给页面级别的 Props
随意的调用 global 中的 Action ,只是需要手动的将 dispatch 函数传递给这些 Action
import * as React from "react";
import { Dispatch } from "redux";
import { connect } from "react-redux";
import { HashRouter as Router, Route, NavLink } from "react-router-dom";
import { IStoreState } from "./global/types";
import * as globalActions from "./global/actions";
import { HomePage } from "./pages/Home";
import { TestPage } from "./pages/TestPage";
import "./style.less";
interface IAppComponentProps {
dispatch: Dispatch;
}
class AppComponent extends React.Component<IAppComponentProps> {
constructor(props: IAppComponentProps) {
super(props);
globalActions.setGlobalSyncId(this.props.dispatch);
}
public render() {
return (
<Router >
<div>
<div className="nav-container">
<NavLink to="/" >Home Page</NavLink>
<NavLink to="/test">Test Page</NavLink>
</div>
<Route exact={true} path="/" component={HomePage} />
<Route path="/test" component={TestPage} />
</div>
</Router>
);
}
}
const mapStateToProps = (state: IStoreState) => {
const { global } = state;
return {
global,
};
};
export const App = connect(mapStateToProps)(AppComponent);