记录 redux 在 typescript 和 hooks 中出现的问题

1,367 阅读1分钟

在子组件使用 redux hooks 的前提:

要父组件或者根组件中调用 Provider 组件,否则报以下错误

image.png

完整伪代码解决方式如下:

// app.tsx
import React from 'react';
import { Provider } from 'react-redux';
import store from './store';
import './App.css';
import Counter from './Counter';
function App(): JSX.Element {
  return (
    <Provider store={store}> // ====> 问题解决关键
      <div className="App">
        <Counter />
      </div>
    </Provider>
  );
}
export default App;

// Counter.tsx
import React from 'react';
import './index.less';
import { useSelector, useDispatch } from 'react-redux';
import { addCounter } from '../store/actions';
function Counter(): JSX.Element {
  const dispatch = useDispatch();
  const count = useSelector(state => state.counter);
  const handleDispatchAdd = (value: number) => {
    dispatch(addCounter(++value));
  };
  return (
    <div className="wrapper">
      {count}
      <Button onClick={() => handleDispatchAdd(count)}> + </Button>
    </div>
  );
}
export default Counter;

// store/index.ts
import { createStore, combineReducers } from 'redux';
import { counter } from './reducer';
const rootReducer = combineReducers({
  counter,
});
const store = createStore(rootReducer);
export default store;

// store/reducer.ts
import { ADD_COUNTER } from './types';
export const counter = (state = 0, action: { type: any; count: any }) => {
  switch (action.type) {
    case ADD_COUNTER:
      return action.count;
    default:
      return state;
  }
};

// store/types.ts
export const ADD_COUNTER = 'ADD_COUNTER'

// store/actions.ts
import { ADD_COUNTER } from './types';
export const addCounter = (count: number) => {
  return {
    type: 'addCounter',
    count,
  };
};

敲完上面代码后,就会发现 useSelector 可以使用,但是会 ts 错误提示:

image.png

解决 类型 “DefaultRootState” 上不存在属性 “xxx” 问题

问题描述:是使用 useSelector 时,state 的默认类型,找不到该属性,那就给 state 增加一个类型属性呗 最简单const count = useSelector(state: {counter: number} => state.counter); 不报错了,新问题增加 redux 其他属性,无法提供 ts 提示

解决方案:

// store/index.ts
import { createStore, combineReducers } from 'redux';
import { counter } from './reducer';
const rootReducer = combineReducers({
  counter,
});
// ==> 增加 rootState 类型
export type RootState = ReturnType<typeof rootReducer>;
const store = createStore(rootReducer);
export default store;

// Counter.tsx
...
import { RootState } from '../store';
function Counter(): JSX.Element {
  const dispatch = useDispatch();
  const count = useSelector((state: RootState) => state.counter);
  ....
}
export default Counter;