Тощилин Сергей
setState
this.setState((state, props) => {
return { counter: state.counter + props.step };
})
render()
export const notesReducer = (
state: ApplicationState,
action: IAction
) => {
switch (action.type) {
case 'INCREMENT_NOTE_COUNTER': {
const { noteCount } = state;
const { newNoteCount } = action;
return {
...state,
noteCount: noteCount + newNoteCount
};
}
...
export const notesReducer = (
state: ApplicationState,
action: IAction
) => {
switch (action.type) {
case 'INCREMENT_NOTE_COUNTER': {
const { noteCount } = state;
const { newNoteCount } = action;
return {
...state,
noteCount: noteCount + newNoteCount
};
}
...
export const notesReducer = (
state: ApplicationState,
action: IAction
) => {
switch (action.type) {
case 'INCREMENT_NOTE_COUNTER': {
const { noteCount } = state;
const { newNoteCount } = action;
return {
...state,
noteCount: noteCount + newNoteCount
};
}
...
export enum NOTE_STATUS {
actual = 'actual',
old = 'old',
deleted = 'deleted'
}
interface IPureNote { ... }
export interface INote extends IPureNote { ... }
export enum ACTIONS { ... }
export enum NOTE_STATUS { ... }
export interface IPureNote { title: string;
description: string;
status: NOTE_STATUS;
created: Date;
}
export interface INote extends IPureNote {
id: number;
}
export enum ACTIONS { ... }
export enum NOTE_STATUS { ... }
export interface IPureNote { ... }
export interface INote extends IPureNote { ... }
// Все типы Action'ов
export enum ACTIONS {
ADD_NOTE = 'ADD_NOTE',
EDIT_NOTE = 'EDIT_NOTE',
CHANGE_STATUS = 'CHANGE_STATUS'
}
// Payloads – ПОЛЕЗНАЯ(!) информация, которая передается в action
export interface IEditNotePayload {
id: number;
newNote: IPureNote;
}
export interface IAddNotePayload { ... }
export interface IChangeStatusPayload { ... }
// Интерфейс, который описывает Action целиком
export interface IAction { ... }
// Payloads – ПОЛЕЗНАЯ(!) информация, которая передается в action
export interface IAddNotePayload { ... }
export interface IEditNotePayload { ... }
export interface IChangeStatusPayload { ... }
// Интерфейс, который описывает Action целиком
export interface IAction {
type: ACTIONS;
payload:
| IAddNotePayload
| IEditNotePayload
| IChangeStatusPayload;
}
import {
IAddNotePayload,
IEditNotePayload,
IChangeStatusPayload,
ACTIONS,
IAction
} from '../common/types';
export const editNote = ({ id, newNote }: IEditNotePayload): IAction =>
({
type: ACTIONS.EDIT_NOTE,
payload: {
id,
newNote
}
});
import {
IAddNotePayload,
IEditNotePayload,
IChangeStatusPayload,
ACTIONS,
IAction
} from '../common/types';
export const editNote = ({ id, newNote }: IEditNotePayload): IAction =>
({
type: ACTIONS.EDIT_NOTE,
payload: {
id,
newNote
}
});
import {
IAddNotePayload,
IEditNotePayload,
IChangeStatusPayload,
ACTIONS,
IAction
} from '../common/types';
export const editNote = ({ id, newNote }: IEditNotePayload): IAction =>
({
type: ACTIONS.EDIT_NOTE,
payload: {
id,
newNote
}
});
import {
IAddNotePayload,
IEditNotePayload,
IChangeStatusPayload,
ACTIONS,
IAction
} from '../common/types';
export const editNote = ({ id, newNote }: IEditNotePayload): IAction =>
({
type: ACTIONS.EDIT_NOTE,
payload: {
id,
newNote
}
});
import { ..., IEditNotePayload, IAction } from '../common/types';
...
// состояние Store при инициализации приложения
export const initialState = { notes: initialNotes };
const notesReducer = (
state: ApplicationState = initialState,
action: IAction
) => {
...
switch (action.type) {
case ACTIONS.EDIT_NOTE:
...
}
};
import { ..., IEditNotePayload, IAction } from '../common/types';
...
// состояние Store при инициализации приложения
export const initialState = { notes: initialNotes };
const notesReducer = (
state: ApplicationState = initialState,
action: IAction
) => {
...
switch (action.type) {
case ACTIONS.EDIT_NOTE:
...
}
};
import { ..., ACTIONS, IAction } from '../common/types';
...
// состояние Store при инициализации приложения
export const initialState = { notes: initialNotes };
const notesReducer = (
state: ApplicationState = initialState,
action: IAction
) => {
...
switch (action.type) {
case ACTIONS.EDIT_NOTE:
...
}
};
import { ApplicationState } from './index';
...
case ACTIONS.EDIT_NOTE: {
const { id, newNote } = action.payload;
const noteWithId = { ...newNote, id };
const noteIndex = state.notes.findIndex(
(note: INote) => note.id === id
);
return {
...state,
notes: [...notes].splice(noteIndex, 1, noteWithId);
};
}
...
import { ApplicationState } from './index';
...
case ACTIONS.EDIT_NOTE: {
const { id, newNote } = action.payload;
const noteWithId = { ...newNote, id };
const noteIndex = state.notes.findIndex(
(note: INote) => note.id === id
);
return {
...state,
notes: [...notes].splice(noteIndex, 1, noteWithId);
};
}
...
import { createStore } from 'redux';
import { INote } from '../common/types';
import reducer, { initialState } from './reducers';
export interface ApplicationState {
notes: INote[];
}
export default createStore(
reducer,
initialState as any
);
import { createStore } from 'redux';
import { INote } from '../common/types';
import reducer, { initialState } from './reducers';
export interface ApplicationState {
notes: INote[];
}
export default createStore(
reducer,
initialState as any
);
import { createStore } from 'redux';
import { INote } from '../common/types';
import reducer, { initialState } from './reducers';
export interface ApplicationState {
notes: INote[];
}
export default createStore(
reducer,
initialState as any
);
import { createStore } from 'redux';
import { INote } from '../common/types';
import reducer, { initialState } from './reducers';
export interface ApplicationState {
notes: INote[];
}
export default createStore(
reducer,
initialState as any
);
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { Route, Switch } from 'react-router-dom';
import store from './store';
export default class App extends Component {
public render() {
return (
<Provider store={store}>
<div className="App">
<Switch>
<Route path="/note/:id" component={Note} />
<Route path="/" component={NotesList} />
</Switch>
</div>
</Provider>
);
}
}
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { Route, Switch } from 'react-router-dom';
import store from './store';
export default class App extends Component {
public render() {
return (
<Provider store={store}>
<div className="App">
<Switch>
<Route path="/note/:id" component={Note} />
<Route path="/" component={NotesList} />
</Switch>
</div>
</Provider>
);
}
}
import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { Route, Switch } from 'react-router-dom';
import store from './store';
export default class App extends Component {
public render() {
return (
<Provider store={store}>
<div className="App">
<Switch>
<Route path="/note/:id" component={Note} />
<Route path="/" component={NotesList} />
</Switch>
</div>
</Provider>
);
}
}
import { connect } from 'react-redux';
import { ApplicationState } from '../../store';
import { changeStatus, editNote } from '../../store/actions';
...
type StateProps = ReturnType<typeof mapStateToProps>;
type DispatchProps = { dispatch: (action: IAction) => void };
type Props = StateProps & DispatchProps & ...;
class Note extends Component<Props, IOwnState> {
...
}
const mapStateToProps = (state: ApplicationState, props: Props) => ({
currentNote: state.notes.find(note => note.id === id);
});
export default connect(mapStateToProps)(Note);
import { connect } from 'react-redux';
import { ApplicationState } from '../../store';
import { changeStatus, editNote } from '../../store/actions';
...
type StateProps = ReturnType<typeof mapStateToProps>;
type DispatchProps = { dispatch: (action: IAction) => void };
type Props = StateProps & DispatchProps & ...;
class Note extends Component<Props, IOwnState> {
...
}
const mapStateToProps = (state: ApplicationState, props: Props) => ({
currentNote: state.notes.find(note => note.id === id);
});
export default connect(mapStateToProps)(Note);
import { connect } from 'react-redux';
import { ApplicationState } from '../../store';
import { changeStatus, editNote } from '../../store/actions';
...
type StateProps = ReturnType<typeof mapStateToProps>;
type DispatchProps = { dispatch: (action: IAction) => void };
type Props = StateProps & DispatchProps & ...;
class Note extends Component<Props, IOwnState> {
...
}
const mapStateToProps = (state: ApplicationState, props: Props) => ({
currentNote: state.notes.find(note => note.id === id);
});
export default connect(mapStateToProps)(Note);
...
type StateProps = ReturnType<typeof mapStateToProps>;
type Props = StateProps & DispatchProps;
class Note extends Component<Props, IOwnState> {
...
public render() {
return (
...
<div className="note-page__field">
Дата создания
<div className="note-page__created-date">
{this.props.currentNote.created}
</div>
</div>
...
)
}
...
}
...
type StateProps = ReturnType<typeof mapStateToProps>;
type Props = StateProps & DispatchProps;
class Note extends Component<Props, IOwnState> {
...
public render() {
return (
...
<div className="note-page__field">
Дата создания
<div className="note-page__created-date">
{this.props.currentNote.created}
</div>
</div>
...
)
}
...
}
...
...
type DispatchProps = { dispatch: (action: IAction) => void };
type Props = StateProps & DispatchProps;
class Note extends Component<Props, IOwnState> {
...
public onEditButtonClick = (e: ReactMouseEvent) => {
...
// Кладем в currentNote данные об отредактированной заметке
const currentNote = ...;
this.props.dispatch({
type: ACTIONS.EDIT_NOTE,
payload: { id, newNote: currentNote }
});
};
...
}
...
...
type DispatchProps = { dispatch: (action: IAction) => void };
type Props = StateProps & DispatchProps;
class Note extends Component<Props, IOwnState> {
...
public onEditButtonClick = (e: ReactMouseEvent) => {
...
// Кладем в currentNote данные об отредактированной заметке
const currentNote = ...;
this.props.dispatch({
type: ACTIONS.EDIT_NOTE,
payload: { id, newNote: currentNote }
});
};
...
}
...
import { editNote } from '../../store/actions';
...
type DispatchProps = { dispatch: (action: IAction) => void };
type Props = StateProps & DispatchProps;
class Note extends Component<Props, IOwnState> {
...
public onEditButtonClick = (e: ReactMouseEvent) => {
...
// Кладем в currentNote данные об отредактированной заметке
const currentNote = ...;
this.props.dispatch(editNote({ id, newNote: currentNote }));
};
...
}
...
import { editNote } from '../../store/actions';
...
type DispatchProps = { dispatch: (action: IAction) => void };
type Props = StateProps & DispatchProps;
class Note extends Component<Props, IOwnState> {
...
public onEditButtonClick = (e: ReactMouseEvent) => {
...
// Кладем в currentNote данные об отредактированной заметке
const currentNote = ...;
this.props.dispatch(editNote({ id, newNote: currentNote }));
};
...
}
...
import { editNote } from '../../store/actions';
...
type DispatchProps = { dispatch: (action: IAction) => void };
type Props = StateProps & DispatchProps;
class Note extends Component<Props, IOwnState> {
...
public onEditButtonClick = (e: ReactMouseEvent) => {
...
// Кладем в currentNote данные об отредактированной заметке
const currentNote = ...;
this.props.dispatch(editNote({ id: [56], newNote: [ЗАМЕТКА] }))
};
...
}
...
import {
IAddNotePayload,
IEditNotePayload,
IChangeStatusPayload,
ACTIONS,
IAction
} from '../common/types';
const editNote = ({ id: [56], newNote: [ЗАМЕТКА] }: IEditNotePayload) =>
({
type: ACTIONS.EDIT_NOTE // 'editNote',
payload: {
id: [56],
newNote: [ЗАМЕТКА]
}
});
...
import { ApplicationState } from './index';
...
case ACTIONS.EDIT_NOTE: { // 'editNote'
const { id: [56], newNote: [ЗАМЕТКА] } = action.payload;
// noteWithId – это [ЗАМЕТКА №56]
const noteWithId = { ...newNote: [ЗАМЕТКА], id: [56] };
// находим индекс редактируемой заметки
const index = state.notes.findIndex(
(note: INote) => note.id === id
);
// копируем массив заметок и вставляем на место старой новую
return {
...state,
notes: [...notes].splice(index, 1, noteWithId: [ЗАМЕТКА №56]);
};
}
...
...
type StateProps = ReturnType<typeof mapStateToProps>;
type DispatchProps = { dispatch: (action: IAction) => void };
type Props = StateProps & DispatchProps & ...;
class Note extends Component<Props, IOwnState> {
...
}
const mapStateToProps = (state: ApplicationState, props: Props) => ({
currentNote: state.notes.find(note => note.id === id: [56]);
// теперь this.props.currentNote – это [ЗАМЕТКА №56]
});
export default connect(mapStateToProps)(Note);
...
type StateProps = ReturnType<typeof mapStateToProps>;
type Props = StateProps & DispatchProps; // подкладываем StateProps в this.props
class Note extends Component<Props, IOwnState> {
...
public render() {
return (
...
<div className="note-page__field">
Дата создания
<div className="note-page__created-date">
{this.props.currentNote.created} // это [ЗАМЕТКА №56]
</div>
</div>
...
)
}
...
}
...
type StateProps = ReturnType<typeof mapStateToProps>;
type Props = StateProps & DispatchProps; // подкладываем StateProps в this.props
class Note extends Component<Props, IOwnState> {
...
public render() {
return (
...
<div className="note-page__field">
Дата создания
<div className="note-page__created-date">
{this.props.currentNote.created} // это [ЗАМЕТКА №56]
</div>
</div>
...
)
}
...
}
Context provides a way to pass data through the component tree without having to pass props down manually at every level