J'essaie de suivre ce code in redux-saga
export const getUser = (state, login) => state.entities.users[login]
export const getRepo = (state, fullName) => state.entities.repos[fullName]
Ce qui est ensuite utilisé dans la saga comme this :
import { getUser } from '../reducers/selectors'
// load user unless it is cached
function* loadUser(login, requiredFields) {
const user = yield select(getUser, login)
if (!user || requiredFields.some(key => !user.hasOwnProperty(key))) {
yield call(fetchUser, login)
}
}
Ce réducteur getUser
(même s'il s'agit d'un réducteur) est très différent de ce à quoi je m'attendrais normalement d'un réducteur.
Quelqu'un peut-il expliquer ce qu'est un sélecteur et comment getUser
est un réducteur et comment il s'inscrit dans redux-saga?
getUser
n'est pas un réducteur, c'est en fait un sélecteur, c'est-à-dire une fonction qui sait comment extraire une donnée spécifique du magasin.
Les sélecteurs fournissent une couche supplémentaire telle que, si vous modifiez la structure de votre magasin et que tout à coup votre users
ne soit plus à state.entities.users
mais à state.users.objects.entities
(ou autre), il vous suffit alors de mettre à jour le sélecteur getUser
dans votre application où vous faisiez référence à l'ancien emplacement.
Cela les rend particulièrement utiles pour refactoriser votre magasin Redux.
Les sélecteurs sont des getters pour l'état redux. Comme les accesseurs, les sélecteurs encapsulent la structure de l'état et sont réutilisables. Les sélecteurs peuvent également calculer des propriétés dérivées.
Vous pouvez écrire des sélecteurs, tels que ceux que vous avez vus dans redux-saga. Par exemple:
const getUsersNumber = ({ users }) => users.length;
const getUsersIds = ({ users }) => users.map(({ id }) => id);
etc...
Vous pouvez également utiliser reselect , qui est une simple bibliothèque de «sélecteur» pour Redux, qui mémorise les sélecteurs pour les rendre plus efficaces.
Les sélecteurs sont des fonctions qui prennent l'état Redux en tant qu'argument et renvoient certaines données à transmettre au composant.
const getUserData = state => state.user.data;
Pourquoi devrait-il être utilisé?
L'utilisation de resélectionner aide à mémoriser les données, ce qui signifie que lorsque la même entrée est transmise à la fonction, le résultat précédent est renvoyé au lieu d'être recalculé à nouveau. Cela améliore donc les performances de votre application.
function mapStateToProps (state) {
return {
user: state.user,
}
}
initialState of reducer by user store
const initialState = {
isAdmin:false,
isAuth:false,
access:[1,2,5]
};
class AppComp extends React.Component{
render(){
const {user: { access:access}} = this.props;
const Rand = Math.floor(Math.random()*4000)
return (<div>
{`APP ${Rand} `}
<input type="button" defaultValue="change auth" onClick={this.onChangeUserAuth} />
<p>TOTAL STATUS COUNT IS {access.length}</p>
</div>)
}
}}
mais vous pouvez utiliser le sélecteur
var getUser = function(state) {
return state.user
}
const getAuthProp = createSelector(
getUser,
(user) => user.access
);
function mapStateToProps (state) {
return {
// user: state.user,
access: getAuthProp(state)
}
}
Le problème principal est que ce composant utilise tous les utilisateurs: state.user et que tout changement d'utilisateur (etc isAdmin, isAuth, access) exécute la restitution de ce composant qui n'a besoin que d'une partie de ce magasin - access !!!
Dans Redux, chaque fois qu'une action est appelée n'importe où dans l'application, tous les composants montés et connectés appellent leur mapStateToProps une fonction. C'est pourquoi Reselect est génial. Il va simplement retourner le résultat mémoisé si rien n'a changé.
Dans le monde réel, vous aurez probablement besoin de la même partie de votre objet d'état dans plusieurs composants.
https://medium.com/@parkerdan/react-reselect-and-redux-b34017f8194c
La fonction createSelector fournie par Reselect implémente le moyen le plus simple de dériver un sélecteur à partir de sélecteurs précédents. Le cas d'utilisation le plus simple consiste à dériver un sélecteur d'un seul autre sélecteur. Dans ce cas, les paramètres à créerSélecteur sont le sélecteur d’entrée et une fonction transformant le résultat de ce sélecteur en résultat du nouveau sélecteur. Par exemple
var getProducts = function(state) {
return state.products
}
import {getProducts} from '../app/selectors'
import {createSelector} from 'reselect'
export const getProductTitles = createSelector(
getProducts,
(products) => products.map((product) => product.get('title'))
)
Cela équivaut à (ignorer la mémorisation):
import {getProducts} from '../app/selectors'
export const getProductTitles = (state) => {
return getProducts(state).map((product) => product.get('title'))
}
La fonction createSelector peut combiner des données provenant de plusieurs sélecteurs ainsi que d'un seul sélecteur. Nous pouvons transmettre n'importe quel nombre de sélecteurs à createSelector, et leurs résultats seront transmis à la fonction transmise comme argument final. Pour un exemple (quelque peu artificiel):
const isInCheckout = createSelector(
getIsShippingPage,
getIsBillingPage,
getIsConfirmationPage,
(isShipping, isBilling, isConfirmation) =>
isShipping || isBilling || isConfirmation
)
est équivalent à
const isInCheckout = (state) => {
return (
getIsShippingPage(state) ||
getIsBilingPage(state) ||
getIsConfirmationPage(state)
)
}
le modèle courant lors de l'écriture de fonctions mapStateToProps avec des sélecteurs consiste à renvoyer un objet avec chaque clé stockant le résultat d'un sélecteur particulier. La fonction d’assistance createStructuredSelector dans Reselect nous permet d’écrire ce modèle avec le minimum requis. Par exemple, si nous écrivons
const mapStateToProps = createStructuredSelector({
title: getProductTitle,
price: getProductPrice,
image: getProductImage
})
c'est équivalent à
const mapStateToProps = (state) => {
return {
title: getProductTitle(state),
price: getProductPrice(state),
image: getProductImage(state)
}
}
https://docs.mobify.com/progressive-web/0.15.0/guides/reselect/