收集至:https://zhuanlan.zhihu.com/p/42141179

无状态组件

  1. import * as React from "react";
  2. const TestPage: React.SFC = () => {
  3. return (
  4. <div>
  5. this is test page.
  6. </div>
  7. );
  8. };
  9. export default TestPage;

当我们需要传递 Props 时,只用定义一个 Props 接口,然后给 props 指明类型:

  1. export interface IHeaderProps {
  2. localImageSrc: string;
  3. onLineImageSrc: string;
  4. }
  5. export const Header: React.SFC<IHeaderProps> = (props: IHeaderProps) => {
  6. const { localImageSrc, onLineImageSrc } = props;
  7. return (
  8. <div className={styles["header-container"]}>
  9. <img src={localImageSrc} />
  10. <img src={onLineImageSrc} />
  11. </div>
  12. );
  13. };

有状态组件

  1. export interface IHomePageState {
  2. name: string;
  3. }
  4. class HomeComponent extends React.Component<{}, IHomePageState> {
  5. constructor(props: {}) {
  6. super(props);
  7. this.state = {
  8. name: "",
  9. };
  10. }
  11. public setName = () => {
  12. this.setState({
  13. name: "icepy",
  14. });
  15. }
  16. public render(){
  17. const { name } = this.state;
  18. return (
  19. <div>
  20. <div onClick={this.setName}> set name </div>
  21. <div>{name}</div>
  22. </div>
  23. )
  24. }
  25. }

Props & State 组件

  1. export interface IHomePageState {
  2. name: string;
  3. }
  4. export interface IHomePageProps {
  5. home: string;
  6. }
  7. class HomeComponent extends React.Component<IHomePageProps, IHomePageState> {
  8. constructor(props: IHomePageProps) {
  9. super(props);
  10. this.state = {
  11. name: "",
  12. };
  13. }
  14. public setName = () => {
  15. this.setState({
  16. name: "icepy",
  17. });
  18. }
  19. public render(){
  20. const { name } = this.state;
  21. const { home } = this.props;
  22. return (
  23. <div>
  24. <div onClick={this.setName}> set name </div>
  25. <div>{name} {home}</div>
  26. </div>
  27. )
  28. }
  29. }

Router 组件

  1. import { RouteComponentProps } from "react-router-dom";
  2. export interface IHomePageProps extends RouteComponentProps<any>{
  3. home: string;
  4. }
  5. export interface IHomePageState {
  6. home: string;
  7. }
  8. class HomeComponent extends React.Component<IHomePageProps, IHomePageState> {
  9. constructor(props: IHomePageProps) {
  10. super(props);
  11. this.state = {
  12. name: "",
  13. };
  14. }
  15. public setName = () => {
  16. this.setState({
  17. name: "icepy",
  18. });
  19. }
  20. public render(){
  21. const { name } = this.state;
  22. const { home } = this.props;
  23. return (
  24. <div>
  25. <div onClick={this.setName}> set name </div>
  26. <div>{name} {home}</div>
  27. </div>
  28. )
  29. }
  30. }

页面级别的 Reducers

为类型安全定义接口:

  1. import { Dispatch } from "redux";
  2. import { RouteComponentProps } from "react-router-dom";
  3. export interface IHomePageActionsProps {
  4. dataSync: () => void;
  5. dataAsync: (parameter: string) => (dispatch: Dispatch) => void;
  6. }
  7. export interface IHomePageProps extends RouteComponentProps<any>, IHomePageActionsProps {
  8. homePage: IHomePageStoreState;
  9. }
  10. export interface IHomePageStoreState {
  11. syncId: string;
  12. asyncId: string;
  13. }
  14. // global dir
  15. export interface IStoreState {
  16. homePage: IHomePageStoreState;
  17. }

定义一个 mapStateToProps 函数:

  1. const mapStateToProps = (state: IStoreState) => {
  2. const { homePage } = state;
  3. return {
  4. homePage,
  5. };
  6. };

定义 Action 和 Reducers:

  1. // action
  2. import * as CONST from "./constants";
  3. import { Dispatch } from "redux";
  4. export function dataSync() {
  5. const syncData = {
  6. type: CONST.SYNC_DATA,
  7. payload: {
  8. data: "syncId=https://github.com/icepy",
  9. },
  10. };
  11. return syncData;
  12. }
  13. export function dataAsync(parameter: string): (dispatch: Dispatch) => void {
  14. return (dispatch: Dispatch) => {
  15. const asyncData = {
  16. type: CONST.ASYNC_DATA,
  17. payload: {
  18. data: "asyncId=https://icepy.me",
  19. },
  20. };
  21. setTimeout(() => {
  22. dispatch(asyncData);
  23. }, 2000);
  24. };
  25. }
  26. // reducers
  27. import { IAction } from "@/global/types";
  28. import * as CONST from "./constants";
  29. import * as TYPES from "./types";
  30. const initState: TYPES.IHomePageStoreState = {
  31. syncId: "默认值",
  32. asyncId: "默认值",
  33. };
  34. export function homeReducers(state = initState, action: IAction): TYPES.IHomePageStoreState {
  35. const { type, payload } = action;
  36. switch (type) {
  37. case CONST.SYNC_DATA:
  38. return { ...state, syncId: payload.data };
  39. case CONST.ASYNC_DATA:
  40. return { ...state, asyncId: payload.data };
  41. default:
  42. return { ...state };
  43. }
  44. }

在 Store 中 引入我们的 reducers:

  1. import { createStore, applyMiddleware, combineReducers, compose } from "redux";
  2. import thunk from "redux-thunk";
  3. import { homeReducers } from "@/pages/Home/flow/homeReducers";
  4. /* eslint-disable no-underscore-dangle, no-undef */
  5. const composeEnhancers = (window as any) && (window as any).REDUX_DEVTOOLS_EXTENSION_COMPOSE || compose;
  6. const reducer = combineReducers({
  7. homePage: homeReducers,
  8. });
  9. export const configureStore = () => createStore(
  10. reducer,
  11. composeEnhancers(applyMiddleware(thunk)),
  12. );

使用 connect 函数将这些关联起来:

  1. class HomeComponent extends React.Component<TYPES.IHomePageProps, TYPES.IHomePageState> {
  2. ... 省略
  3. }
  4. export const HomePage = connect(mapStateToProps, actions)(HomeComponent);

Global级别的 Reducers

global 顾名思义,这是一种可以全局访问的 reducers ,我们要做的事情也和页面级别 reducers 非常类似,定义好 state 的接口,然后将 global 在 Store 中配置正确,如:

  1. import { createStore, applyMiddleware, combineReducers, compose } from "redux";
  2. import thunk from "redux-thunk";
  3. import { homeReducers } from "@/pages/Home/flow/homeReducers";
  4. import { globalReducers } from "./reducers";
  5. const composeEnhancers = (window as any) && (window as any).REDUX_DEVTOOLS_EXTENSION_COMPOSE || compose;
  6. const reducer = combineReducers({
  7. global: globalReducers,
  8. homePage: homeReducers,
  9. });
  10. export const configureStore = () => createStore(
  11. reducer,
  12. composeEnhancers(applyMiddleware(thunk)),
  13. );

当我们需要访问 global 时,有两种方式:

  1. 在 mapStateToProps 函数中将 global 返回给页面级别的 Props

  2. 随意的调用 global 中的 Action ,只是需要手动的将 dispatch 函数传递给这些 Action

  1. import * as React from "react";
  2. import { Dispatch } from "redux";
  3. import { connect } from "react-redux";
  4. import { HashRouter as Router, Route, NavLink } from "react-router-dom";
  5. import { IStoreState } from "./global/types";
  6. import * as globalActions from "./global/actions";
  7. import { HomePage } from "./pages/Home";
  8. import { TestPage } from "./pages/TestPage";
  9. import "./style.less";
  10. interface IAppComponentProps {
  11. dispatch: Dispatch;
  12. }
  13. class AppComponent extends React.Component<IAppComponentProps> {
  14. constructor(props: IAppComponentProps) {
  15. super(props);
  16. globalActions.setGlobalSyncId(this.props.dispatch);
  17. }
  18. public render() {
  19. return (
  20. <Router >
  21. <div>
  22. <div className="nav-container">
  23. <NavLink to="/" >Home Page</NavLink>
  24. <NavLink to="/test">Test Page</NavLink>
  25. </div>
  26. <Route exact={true} path="/" component={HomePage} />
  27. <Route path="/test" component={TestPage} />
  28. </div>
  29. </Router>
  30. );
  31. }
  32. }
  33. const mapStateToProps = (state: IStoreState) => {
  34. const { global } = state;
  35. return {
  36. global,
  37. };
  38. };
  39. export const App = connect(mapStateToProps)(AppComponent);