Свойство isFetching не существует для типа never. с mapStateToProps - PullRequest
0 голосов
/ 05 мая 2020

Я пытаюсь сопоставить состояние моего магазина с моими реквизитами с помощью mapStateToProps. В частности, свойство isFetching в состоянии authentication моего магазина. Однако Typescript сообщает мне

Property 'isFetching' does not exist on type 'never'.

Не совсем уверен, что не так. Похоже на проблему типа, но я не уверен, в чем проблема.

interface IMapStateToProps {
  isFetching: boolean;
}

const mapStateToProps = (
  state: AppState,
): IMapStateToProps => ({
  isFetching: state.authentication.isFetching,
});

Отображает ошибку: Property 'isFetching' does not exist on type 'never'.

Однако приведенный ниже код:

const mapStateToProps = (
  state: AppState,
  ownProps: AuthenticationPageProps
): IMapStateToProps => {
  console.log(state.authentication);
  return { isFetching: false };
};

Производит:

errors: []
isFetching: false
user: null

Магазин:

import { createStore, applyMiddleware, combineReducers } from "redux";
import thunk, { ThunkMiddleware } from "redux-thunk";
import { authenticationReducer } from "../reducers/authenticationReducer";
import { AppActions } from "../../types/AppActionTypes";

const initialState = {};

export const rootReducer = combineReducers({
  authentication: authenticationReducer,
});
export type AppState = ReturnType<typeof rootReducer>;
const middlewares = [thunk as ThunkMiddleware<AppState, AppActions>];

const store = createStore(
  rootReducer,
  applyMiddleware(...middlewares)
);

export default store;

Типы:

import { Error } from "./Error";
import { User } from "./User";

export const LOGIN_REQUEST = "LOGIN_REQUEST";
export const LOGIN_SUCCESS = "LOGIN_SUCCESS";
export const LOGIN_FAILURE = "LOGIN_FAILURE";

export const LOGOUT_REQUEST = "LOGOUT_REQUEST";
export const LOGOUT_SUCCESS = "LOGOUT_SUCCESS";
export const LOGOUT_FAILURE = "LOGOUT_FAILURE";

export const REGISTER_REQUEST = "REGISTER_REQUEST";
export const REGISTER_SUCCESS = "REGISTER_SUCCESS";
export const REGISTER_FAILURE = "REGISTER_FAILURE";

export const CHECK_LOGGED_IN_REQUEST = "CHECK_LOGGED_IN_REQUEST";
export const CHECK_LOGGED_IN_FAILURE = "CHECK_LOGGED_IN_FAILURE";
export const CHECK_LOGGED_IN_SUCCESS = "CHECK_LOGGED_IN_SUCCESS";

export interface AuthenticationState {
  isFetching: boolean;
  user: User | null;
  errors: Error[];
}

export interface LoginRequestAction {
  type: typeof LOGIN_REQUEST;
  isFetching: boolean;
}

export interface LoginSuccessAction {
  type: typeof LOGIN_SUCCESS;
  isFetching: boolean;
  user: {
    email: string;
  };
}

export interface LoginFailureAction {
  type: typeof LOGIN_FAILURE;
  isFetching: boolean;
}

export interface LogoutRequestAction {
  type: typeof LOGOUT_REQUEST;
  isFetching: boolean;
}

export interface LogoutSuccessAction {
  type: typeof LOGOUT_SUCCESS;
  isFetching: boolean;
}

export interface LogoutFailureAction {
  type: typeof LOGOUT_FAILURE;
  isFetching: boolean;
}

export interface RegisterRequestAction {
  type: typeof REGISTER_REQUEST;
  isFetching: boolean;
}

export interface RegisterSuccessAction {
  type: typeof REGISTER_SUCCESS;
  isFetching: boolean;
}

export interface RegisterFailureAction {
  type: typeof REGISTER_FAILURE;
  isFetching: boolean;
}

export interface CheckLoggedInRequestAction {
  type: typeof CHECK_LOGGED_IN_REQUEST;
  isFetching: boolean;
}

export interface CheckLoggedInSuccesstAction {
  type: typeof CHECK_LOGGED_IN_SUCCESS;
  isFetching: boolean;
}

export interface CheckLoggedInFailureAction {
  type: typeof CHECK_LOGGED_IN_FAILURE;
  isFetching: boolean;
}

export type AuthenticationActionTypes =
  | RegisterFailureAction
  | RegisterSuccessAction
  | RegisterRequestAction
  | LoginFailureAction
  | LoginRequestAction
  | LoginSuccessAction
  | LogoutFailureAction
  | LogoutRequestAction
  | LogoutSuccessAction
  | CheckLoggedInFailureAction
  | CheckLoggedInRequestAction
  | CheckLoggedInSuccesstAction;

Редуктор:

import {
  LOGOUT_SUCCESS,
  LOGOUT_REQUEST,
  LOGOUT_FAILURE,
  LOGIN_FAILURE,
  LOGIN_SUCCESS,
  LOGIN_REQUEST,
  REGISTER_FAILURE,
  REGISTER_SUCCESS,
  REGISTER_REQUEST,
  AuthenticationState,
  AuthenticationActionTypes,
  CHECK_LOGGED_IN_REQUEST,
  CHECK_LOGGED_IN_SUCCESS,
  CHECK_LOGGED_IN_FAILURE,
} from "../../types/Authentication";

export const AuthenticationReducerDefaultState = {
  errors: [],
  isFetching: false,
  user: null,
};

export const authenticationReducer = (
  state = AuthenticationReducerDefaultState,
  action: AuthenticationActionTypes
): AuthenticationState => {
  switch (action.type) {
    case LOGIN_REQUEST:
    case LOGOUT_REQUEST:
    case REGISTER_REQUEST:
    case CHECK_LOGGED_IN_REQUEST:
      return {
        ...state,
        isFetching: true,
      };
    case LOGIN_SUCCESS:
      return {
        ...state,
        isFetching: false,
        user: {
          email: action.user.email,
        },
      };
    case LOGOUT_SUCCESS:
      return { ...state, isFetching: false };
    case CHECK_LOGGED_IN_SUCCESS:
      return { ...state, isFetching: false };
    case REGISTER_SUCCESS:
      return { ...state, isFetching: false };
    case LOGIN_FAILURE:
      return { ...state, isFetching: false };
    case LOGOUT_FAILURE:
      return { ...state, isFetching: false };
    case REGISTER_FAILURE:
      return { ...state, isFetching: false };
    case CHECK_LOGGED_IN_FAILURE:
      return { ...state, isFetching: false };
    default:
      return state;
  }
};

компонент:

interface AuthenticationPageProps {
  location: { state: string };
}

interface AuthenticationPageState {
  email: string;
  password: string;
  passwordConfirmation: string;
  errors: string;
}

type Props = AuthenticationPageProps & IMapDispatchToProps & IMapStateToProps;

const AuthenticationPage = (props: Props) => {
  const [lostPasswordState, setLostPasswordState] = useState("");
  const [registerState, setRegisterState] = useState({
    email: "",
    password: "",
    passwordConfirmation: "",
  });
  const [loginState, setLoginState] = useState({
    email: "",
    password: "",
  });

  const handleLostPasswordSubmit = (event: SyntheticEvent) => {
    console.log("Lost Password Form submitted");
    event.preventDefault();
  };

  const handleLoginSubmit = (event: SyntheticEvent) => {
    console.log("Login Form submitted");
    event.preventDefault();
    props.login(loginState.email, loginState.password);
  };

  const handleRegistrationSubmit = (event: SyntheticEvent) => {
    console.log("Registration Form submitted");
    event.preventDefault();
    props.register(
      registerState.email,
      registerState.password,
      registerState.passwordConfirmation
    );
  };

  const handleLoginOnChange = (event: React.ChangeEvent<HTMLInputElement>) => {
    setLoginState({
      ...loginState,
      [event.target.name]: event.target.value,
    });
  };

  const handleLostPasswordOnChange = (
    event: React.ChangeEvent<HTMLInputElement>
  ) => {};

  const handleRegisterOnChange = (
    event: React.ChangeEvent<HTMLInputElement>
  ) => {
    setRegisterState({
      ...registerState,
      [event.target.name]: event.target.value,
    });
  };

  return (
    <React.Fragment>
      login
      <LoginForm onSubmit={handleLoginSubmit} onChange={handleLoginOnChange} />
      register
      <RegistrationForm
        onSubmit={handleRegistrationSubmit}
        onChange={handleRegisterOnChange}
      />
      lost password
      <LostPasswordForm
        onSubmit={handleLostPasswordSubmit}
        onChange={handleLostPasswordOnChange}
      />
    </React.Fragment>
  );
};

interface IMapStateToProps {
  isFetching: boolean;
}

interface IMapDispatchToProps {
  login: (email: string, password: string) => void;
  register: (
    email: string,
    password: string,
    passwordConfirmation: string
  ) => void;
}

const mapStateToProps = (
  state: AppState,
  ownProps: AuthenticationPageProps
): IMapStateToProps => {
  console.log(state.authentication);
  return { isFetching: false };
};
const mapDispatchToProps = (
  dispatch: ThunkDispatch<any, any, AuthenticationActionTypes>,
  ownProps: AuthenticationPageProps
): IMapDispatchToProps => ({
  login: bindActionCreators(login, dispatch),
  register: bindActionCreators(register, dispatch),
});

export default connect(mapStateToProps, mapDispatchToProps)(AuthenticationPage);
...