ReactJS и Redux - правильное создание компонента класса connect с типами - PullRequest
3 голосов
/ 30 октября 2019

Итак, я начал изучать React + Redux.

Я получил следующий редуктор:

/**
 * Import custom types.
 */
import { User } from "../types/user.type";
import { Action } from "../types/reducers/profileReducer.type";

/**
 * Creates profile reducer to set and retrieve currently logged in user.
 * @param user - User object, indicating the current state.
 * @param action - Action object, which will indicate which action to apply.
 * @returns User object after the action applied.
 */
const profileReducer = (user: User | null = null, action: Action) => {
  switch(action.type) {
    case 'SET_PROFILE': // Set users profile
      return user = action.payload ? action.payload.user : null;
    default: // Let's set the default action to retrieve the users profile
      return user;
  }
};

/**
 * Export default reducer.
 */
export default profileReducer;

И следующее действие -

/**
 * Import custom types.
 */
import { User } from '../types/user.type';
import { Action } from '../types/reducers/profileReducer.type';

/**
 * Returns an action for setting a profile.
 * @param user - User object which should be set as current users profile.
 * @returns Action for setting a new users profile object.
 */
export const setProfile = (user: User): Action => {
  return {
    type: 'SET_PROFILE',
    payload: {
      user 
    }
  };
}

/**
 * Export all profile actions.
 */
export default {
  setProfile
}

Наконец,это типы -

profileReducer:

/**
 * Import custom types.
 */
import { User } from "../user.type";

export interface Action {
  type: ActionType; // Type of the action
  payload?: {
    user: User; // User object which will be set upon 'SET_PROFILE' action
  }
};

export type ActionType = 'SET_PROFILE';

Пользователь:

export interface User {
  id: string; // ID of the user
  name: string; // Name of the user
  lastName: string; // Last name of the user
  email: string; // Email of the user
  admin: boolean; // Boolean indicator if the user is admin
  active: boolean; // Boolean indicator if the user is active
  gender: boolean; // Gender of the user
  createdAt: string; // Date object when the user was created
  updatedAt: string; // Date object when the user was updated
  birthDate: number; // Date when user was born
  birthYear: number; // Year when user was born
  birthMonth: number; // Month when user was born
}

Теперь у меня есть следующий компонент класса -

/**
 * Import React libraries.
 */
import React, { Dispatch } from 'react';
import { Link, Redirect } from 'react-router-dom';

/**
 * Import third-party libraries.
 */
import Navbar from 'react-bootstrap/Navbar';
import Col from 'react-bootstrap/Col';
import Row from 'react-bootstrap/Row';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { connect } from 'react-redux';

/**
 * Import custom reducer actions.
 */
import actions from '../../actions';

/**
 * Import custom types.
 */
import { HeaderProps } from '../../types/header.type';
import { User } from '../../types/user.type';
import { Action } from '../../types/reducers/profileReducer.type';

/**
 * Import custom scss.
 */
import './Header.scss';

/**
 * Creates Header component class.
 */
class HeaderComponent extends React.Component<HeaderProps> {
  /**
   * Renders Header component view.
   */
  render() {
    return (
      <Row>
        <Col md="12">
          { !this.state.isLoggedIn && <Redirect to="/" /> }
          <Navbar bg="light" expand="lg" className="app-header">

          { /* Style for medium and larger devices */ }
          <div className="d-none d-md-block text-right w-100">
            <Link to="/profile" className="text-dark">
              <FontAwesomeIcon icon="user" className="mr-2" />
              { this.props.profile && `${this.props.profile.name} ${this.props.profile.lastName}` }
            </Link>
          </div>
          </Navbar>
        </Col>
      </Row>
    )
  }
}

/**
 * Creates profile state and sets as parameters for the header component.
 * @param state - Redux store state object.
 */
const mapStateToProps = (state: any) => ({ profile: state.profile });

/**
 * Creates a dispatch mapping, which will be passed in to properties.
 * @param dispatch - Dispatch parameter which takes in a specific action.
 */
const mapDispatchToProps = (dispatch: Dispatch<Action>) => ({
  setProfile: (user: User) => dispatch(actions.profile.setProfile(user))
});

/**
 * Export default header component.
 */
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(HeaderComponent);

И HeaderProps выглядит следующим образом:

export interface HeaderProps {
  profile?: User; // Currently logged in users profile
  setProfile?: Function; // Dispatch function on redux.
}

В настоящее время возникает несколько вопросов:

1) Если я уберу необязательный знак (?) Из свойств HeaderProps, приложение activJs больше не будет компилироваться и будет жаловатьсяо недостающих свойствах в родительском компоненте, в котором я называю компонент заголовка. Это связано с тем, что я не передаю никакое свойство при вызове <Header />, то есть я просто вызываю <Header /> вместо <Header setProfile={..} profile={} />, потому что очевидно - мы извлекаем их из функции connect, верно? Как это исправить?

2) Какие типы я должен использовать для государства? Где у меня сейчас 1030 *? Я не могу понять это.

3) Правильно ли я использовал типы для функции mapDispatchToProps? Если нет, что бы вы изменили?

4) Правильно ли я определил тип компонента? Я не могу получить доступ к стандартным функциям реагирования, таким как setState и т. Д. Должен ли я сам определять их в типе HeaderProps?

5) Видите ли вы какие-либо проблемы в том, как я использовал избыточность? В учебном пособии они разделили их на два отдельных файла - один, содержащий реализацию заголовка, и второй, содержащий избыточное соединение с заголовком. Хорошо, как я это делаю?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...