Parece por que falar sobre Redux em 2020. Afinal, existem muitas alternativas excelentes no campo dos gerentes de estado ( por exemplo ). Afinal, existem cerca de uma dúzia de razões para não amar o Redux, sobre as quais muitos artigos foram escritos e muitos relatórios foram feitos. No entanto, algo não pode ser tirado dele - você pode escrever um site grande, funcional, suportado e rápido nele. Abaixo, vou falar sobre técnicas que ajudam a fazer isso usando o react-redux. Interessante? Bem-vindo ao gato.

aviso Legal Para uma pessoa que leu cuidadosamente a documentação, a quebra da capa não ocorrerá. Seu capitão.
Pessoalmente, eu amo Redux. Para simplicidade e minimalismo. A biblioteca não faz mágica. Onde não há mágica, não há como quebrar algo acidentalmente, sem saber o que você quebrou. O controle retorna às mãos do programador, que, por um lado, libera as mãos e, por outro, requer compreensão ao usá-lo. A discussão abaixo se concentrará no uso "compreensivo" - técnicas que, no primeiro casal, exigem consciência e disciplina, mas são percebidas como algo natural.
Sobre uma loja e estado
Brevemente sobre esses dois conceitos, para que não haja confusão.
Store redux — , state , state, state, - . ""
State redux-store , , , , , . State . ""
mapStateToProps
connect
, , HOC-, store
. connect
mapStateToProps
. mapStateToProps
. mapStateToProps
( , ).
1 mapStateToProps
.
,
const mapStateToProps = () => {
return {
units: [1, 2, 3]
}
}
const UNITS = [1, 2, 3];
const mapStateToProps = () => {
return {
units: UNITS
}
}
, react-redux , . mapStateToProps
. mapStateToProps
shallowEqual
( ). .. , , .
, [1, 2, 3]
, shallowEqual
. , .
, return
- mapStateToProps
, . , , - . UNITS
- selectUserUnits(state, userId)
. .
reselect
.. state — , : state.todos[42].title
. , . , . , redux .
reselect — , . -, readme , . -, reselect . -, ( , ) .
2 reselect , .
. , , , mapStateToProps
.
reselect
. , :
export const selectPriceWithDiscountByProductId = (state, id) => {
const {price, discount} = state.product[id];
return {price, discount};
};
export const selectTagsByProductId = (state, id) => state.product[id].tags || [];
, mapStateToProps
, . , tags
. , reselect
( faiwer — :) ).
, :
const EMPTY_ARRAY = Immutable([]);
export const selectTagsByProductId = (state, id) => state.product[id].tags || EMPTY_ARRAY;
3 reselect , .
. . const selectUserById = (state, id) => state.user[id]
,
reselect . , createSelector
, .
createSelector(...inputSelectors | [inputSelectors], resultFunc)
inputSelectors
— , . resultFunc
, .
const selectUserTagById = (state, userId) => state.user[userId].tag;
const selectPictures = state => state.picture;
const selectRelatedPictureIds = createSelector(
selectUserTagById,
selectPictures,
(tag, pictures) => (
Object.values(pictures)
.filter(picture => picture.tags.includes(tag))
.map(picture => picture.id)
)
)
, , , . , .
, reselect , :
- (
shallowEqual
), . , id , reselect inputSelectors
( shallowEqual
), . , - , reselect selectUserTagById
selectPictures
. pictures
tag
, reselect .
4 .
selectUser({user})
inputSelectors
. reselect, : 1. , . , . , RelatedPictures
,
import {connect} from 'react-redux';
import {RelatedPictures} from '../components';
import {selectRelatedPictureIds} from '../selectors';
const mapStateToProps = (state, {userId}) => {
return {
pictureIds: selectRelatedPictureIds(state, userId)
}
};
export default connect(mapStateToProps)(RelatedPictures);
const RelatedPicturesList = ({userIds}) => (
<div>
{Array.isArray(userIds) && (
userIds.map(id => <RelatedPictureContainer userId={id} />
)}
</div>
)
RelatedPicturesList
, RelatedPictureContainer
mapStateToProps
pictureIds
, selectRelatedPictureIds
userId
. , , RelatedPictures
ShouldComponentUpdate
, .
reselect
5 .
, mapStateToProps
, . react-redux , mapStateToProps
, , mapStateToProps
const selectUserTagById = (state, id) => state.user[id].tag;
const selectPictures = (state, id) => state.picture;
const createRelatedPictureIdsSelector = () => createSelector(
selectUserTagById,
selectPictures,
(tag, pictures) => (
Object.values(pictures)
.filter(picture => picture.tags.includes(tag))
.map(picture => picture.id)
)
)
import {connect} from 'react-redux';
import {RelatedPictures} from '../components';
import {createRelatedPictureIdsSelector} from '../selectors';
const createMapStateToProps = () => {
const selectRelatedPictureIds = createRelatedPictureIdsSelector();
return (state, {userId}) => {
return {
pictureIds: selectRelatedPictureIds(state, userId)
};
};
};
export default connect(createMapStateToProps)(RelatedPictures);
RelatedPicturesContainer
selectRelatedPictureIds
. 1. - userId
, . . , react-, relatedPictureIds
, GC .
. "? ? , , ?". re-reselect, . , mapStateToProps
6 re-reselect
. , . , , , , , Node.js Server Side Rendering. , , , .
connect
mapStateToProps
. , connect
' .
connect(mapStateToProps, mapDispatchToProps, mergeProps, options)
, react-redux . , mapStateToProps
(state), . mapDispatchToProps
.
7 mapStateToProps
mapDispatchToProp
connect'
, mergeProps
. mergeProps
( ) mapStateToProps
mapDispatchToProps
. , , , . . , : connect(mapStateToProps, null, x => x)
.
react-redux . , mapStateToProps
null
, ( , ). , . mapStateToProps
( ), mergeProps
.
, options
connect
. . , mapStateToProps
, mapDispatchToProps
mergeProps
shallowEqual
. . , mapStateToProps
.
8 connect
, . , shouldComponentUpdate
— .
redux . -, . , .
React-redux — . , ( MVVM). , , . , , . shouldComponentUpdate
(useRef
).
Bem, na conclusão muito, muito. Espero que o leitor encontre pelo menos algumas dicas úteis - significa que não foi em vão que ele escreveu. Todo castor)