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