我有一条具有登录和注销按钮的路由,浏览器中的错误是类型'{}'上不存在'属性'dispatch'。'
(home.tsx)
import React, { useContext, useEffect, useRef, useState } from 'react';
import { Dispatch, Global } from '../components/context';
import { LOG_IN, LOG_OUT} from '../components/reducer';
const Home: React.FC = () => {
const { global } = useContext(Global);
const { dispatch } = useContext(Dispatch);
const login = () => {
dispatch({ type: LOG_IN});
};
const logout = () => {
dispatch({ type: LOG_OUT});
};
return (
<div>
{global.loggedIn && <div>You are logged in</div>}
{!global.loggedIn && <div>You are logged out</div>}
<br/>
<button onClick={login}>Log In</button>
<button onClick={logout}>Log Out</button>
</div>
);
};
export { Home };
我认为上下文有误
(context.tsx)
import { createContext } from 'react';
import { InitialState } from './reducer';
const Dispatch = createContext({}); // <--- I'm missing somthing here??
const Global = createContext({
global: InitialState,
});
export { Dispatch, Global };
减速器感觉正确
(reducer.tsx)
const LOG_IN = 'LOG_IN';
const LOG_OUT = 'LOG_OUT';
interface StateInterface {
loggedIn: boolean;
}
const InitialState: StateInterface = {
loggedIn: true,
};
interface ActionInterface {
type: string;
}
const Reducer = (state: StateInterface, action: ActionInterface) => {
switch (action.type) {
case 'LOG_IN':
return {
...state,
loggedIn: true,
};
case 'LOG_OUT':
return {
...state,
loggedIn: false,
};
default:
return state;
}
};
export { Reducer, InitialState, LOG_IN, LOG_OUT };
我认为正确的路线
(Router.tsx)
import React, { useReducer } from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import { Dispatch, Global } from './components/context';
import { Layout } from './components/layout';
import { InitialState, Reducer } from './components/reducer';
import { Home } from './routes/home';
import { NotFound } from './routes/notFound';
const Router: React.FC = () => {
const [global, dispatch] = useReducer(Reducer, InitialState);
return (
<Dispatch.Provider value={{ dispatch }}>
<Global.Provider value={{ global }}>
<BrowserRouter>
<Route
render={({ location }) => (
<Layout location={location}>
<Switch location={location}>
<Route exact path='/' component={Home} />
<Route component={NotFound} />
</Switch>
</Layout>
)}
/>
</BrowserRouter>
</Global.Provider>
</Dispatch.Provider>
);
};
export { Router };
答案 0 :(得分:1)
将稍后将使用的属性设置为Context的初始值。否则,在第一次渲染时使用Context的任何Component都将获得未定义的属性。
因此,请为提供者稍后填充的属性设置某种值,或者如果属性存在,则签入使用Context的每个组件(不建议)。
import { Dispatch as ReactDispatch } from "react";
// We assign the same type the property is going to have later
const Dispatch = createContext<{ dispatch: ReactDispatch<ActionInterface> }>({
dispatch: () => {}
});