在子组件使用 redux hooks 的前提:
要父组件或者根组件中调用 Provider 组件,否则报以下错误
完整伪代码解决方式如下:
// 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 错误提示:
解决 类型 “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;