2017-10-24 2 views
0

Ich bin neu zu wählen und ich verstehe die Notwendigkeit. Ich finde es großartig. Aber in meinem Fall scheint es so, als würde es ohne Grund viel zusätzlichen Code hinzufügen. Vielleicht mache ich es falsch.Ist die Neuauswahl erforderlich, wenn ich nur den normalen Status einer Komponente zuordne?

Zurück Komponente:

const mapStateToProps = (state) => { 
    return { 
     day: state.filters.day, 
     minDate: state.filters.minDate, 
     maxDate: state.filters.maxDate, 
    }; 
}; 

Jetzt Selektoren:

import { createSelector } from 'reselect'; 

const getDay = state => state.filters.day; 
export const makeGetDay =() => createSelector(
    getDay, 
    day => day, 
); 

const getMinDate = state => state.filters.minDate; 
export const makeGetMinDate =() => createSelector(
    getMinDate, 
    date => date, 
); 

const getMaxDate = state => state.filters.maxDate; 
export const makeGetMaxDate =() => createSelector(
    getMaxDate, 
    date => date, 
); 

Jetzt Komponente:

const makeMapStateToProps =() => { 
    const getDay = makeGetDay(); 
    const getMinDate = makeGetMinDate(); 
    const getMaxDate = makeGetMaxDate(); 
    return state => ({ 
     day: getDay(state), 
     minDate: getMinDate(state), 
     maxDate: getMaxDate(state), 
    }); 
}; 

Um zu klären, der Code funktioniert, ich verstehe einfach nicht, was neu wählen in diesem Fall fügt ..

+0

AFAIK, erneut auswählen merkt sich auch den resultierenden Wert. Wenn Sie den Selektor an vielen Stellen verwenden, rufen Sie die Funktion nicht jedes Mal auf. –

+0

Aber wie ist das anders als nur sich selbst auszuwählen? Ich bekomme es, wenn es darum geht, ein Array zu filtern, aber wenn es nicht ist? –

+0

Und man könnte sagen, dass es sich vom Laden entkoppelt, aber wie macht es das, da es immer noch darauf ankommt, dass es einen Laden gibt, der ein Objekt namens filter hat und drinnen Tag, minDate und maxDate? –

Antwort

1

in den Fällen, Sie in Ihrer Frage angegeben haben Reselect nicht wirklich einen beliebigen Wert hinzufügen.

Der Grund dafür ist, dass connect von react-redux bereitgestellt wird es tut eigene seicht ist die in Ihrer mapStateToProps Funktion versehen Requisiten vergleichen, um zu bestimmen, ob ein erforderlich machen. In den von Ihnen bereitgestellten Beispielen, wenn sich die Werte day, minDate oder maxDate nicht ändern, verschwenden Sie keine Zeit mit unnötigen Renderings.

Der reale Wert von Reselect kommt in, wenn Ihr Selektor etwas zurückgibt, das berechnet wird.

Um ein Beispiel aus Vlad zu leihen. Reselect ist für Selektoren so Ihre Selektoren Komponieren wie folgt aussehen:

const mapStateToProps = state => ({ 
    isOutOfRange: getIsDateOutOfRange(state) 
}); 

In diesem Fall Reselect ist für eine nette Syntax bietet Selektoren kombiniert:

export const getDay = state => state.filters.day; 
export const getMinDate = state => state.filters.minDate; 
export const getMaxDate = state => state.filters.maxDate; 

export const getIsDateOutOfRange = createSelector(
    getDay, 
    getMinDate, 
    getMaxDate, 
    (day, minDate, maxDate) => day > maxDate || day < minDate 
); 

Und Ihre mapStateToProps Funktion kann wie folgt aussehen und eine geringfügige Leistung profitiert von der Tatsache, dass getIsDateOutOfRange nur neu berechnet wird, wenn einer der abhängigen Selektoren einen anderen Wert zurückgibt.

Und da liegt der versteckte Leistungsvorteil von Reselect. Wenn Sie über einen Selektor verfügen, der ein berechnetes Array oder ein Objekt zurückgibt, werden zwei identische Werte, die vom Selektor zurückgegeben werden, keine flache Gleichheitsprüfung bestehen, die Reselect oder connect für Memozwecke verwendet.

[0, 1] === [0, 1] // false 

Also für ein konstruiertes Beispiel:

export const getDays = state => state.filters.days; 
export const getMinDate = state => state.filters.minDate; 
export const getMaxDate = state => state.filters.maxDate; 

export const getDaysWithinRangeNotPerformant = state => { 
    const days = getDays(state); 
    const minDate = getMinDate(state); 
    const maxDate = getMaxDate(state); 
    return days.filter(day => day > minDate && day < maxDate); 
}; 

export const getDaysWithinRangePerformant = createSelector(
    getDay, 
    getMinDate, 
    getMaxDate, 
    (days, minDate, maxDate) => 
     days.filter(day => day > minDate && day < maxDate) 
); 

Der Performance-Vorteil, dass Reselect hier entriegelt ist zweifach.

Erst bei mehreren Aufrufen an getDaysWithinRangePerformant wird der möglicherweise teure filter nur ausgeführt, wenn sich die aktuellen Parameter geändert haben.

Zweitens und am wichtigsten ist, getDaysWithinRangeNotPerformant jedes Mal von connect genannt wird, wird es ein neues Array zurück, was bedeutet, dass die flache in connect die Stütze vergleichen wird falsch und render wird wieder einmal aufgerufen werden, wenn die tatsächlichen Tage selbst haben nicht geändert. Weil getDaysWithinRangePerformant durch createSelector Memo ist, wird es genau die gleiche Array-Instanz zurückgeben, wenn sich die Werte nicht geändert haben und daher der flache Vergleich von Requisiten in connect wahr ist und es in der Lage ist, eigene Optimierungen durchzuführen und unnötiges Rendering zu vermeiden.

Und das ist meiner Meinung nach der große Vorteil, Reselect bietet.

2

Zunächst einmal - die Sie nicht verwenden müssen, um überall Funktion höherer Ordnung reselect zu verwenden. Es sieht so aus, als ob du unnötige Schritte machst.

immer von Funktionen höherer Ordnung zu befreien:

-Code unten warks die gleiche Art und Weise, sieht aber viel besser lesbar (kompakt)

export const getDay = createSelector(
    state => state.filters.day, 
    day => day, 
); 

export const getMinDate = createSelector(
    state => state.filters.minDate, 
    date => date, 
); 

export const getMaxDate = createSelector(
    state => state.filters.maxDate, 
    date => date, 
); 

const mapStateToProps = state => ({ 
    day: getDay(state), 
    minDate: getMinDate(state), 
    maxDate: getMaxDate(state), 
}); 

Sie können sogar noch weiter gehen. Sieht so aus, als würdest du Variablen einige Male mal umbenennen, während sie zur Komponente gehen.

store.maxDate -> date -> maxDate

Sie können Ihre „Wähler“ nicht nur verantwortlich für das Abrufen von Daten aus Speicher bilden, sondern auch für folgende Namenskonvention.

export const getDay = createSelector(
    state => state.filters.day, 
    day => ({ day }), 
); 

export const getMinDate = createSelector(
    state => state.filters.minDate, 
    minDate => ({ minDate }), 
); 

export const getMaxDate = createSelector(
    state => state.filters.maxDate, 
    maxDate => ({ maxDate }), 
); 

const mapStateToProps = state => ({ 
    ...getDay(state), 
    ...getMinDate(state), 
    ...getMaxDate(state), 
}); 

Vielleicht Vorteile von composition von Selektoren werden clearlier wenn Sie möchten, einen weiteren Selektor erstellen, basierend auf vorherigen:

Angenommen, Sie eine Komponente haben, die einen Fehler zeigt, wenn day ist definiert außerhalb des Bereichs von maxDate und minDate

export const isDateOutOfRange = createSelector(
    getDay, 
    getMinDate, 
    getMaxDate, 
    ({ day }, { minDate }, { maxDate }) => day > maxDate || day < minDate, 
); 

const mapStateToProps = state => ({ 
    showError: isDateOutOfRange(state), 
}); 
+0

Ok, ich stimme zu, wie man diesen Code mehr macht lesbar, aber warum? Was ist der Vorteil, in diesem Fall erneut zu verwenden? Ich meine, das ist besser lesbar, aber es ist noch besser lesbar, indem man einfach den Zustand auf Props abbildet ... –

+0

Nur der Vorteil der Verwendung des aktuellen Beispiels ist, soweit ich es sehen kann, Auswendiglernen und die Fähigkeit Selektoren in verschiedenen Komponenten wiederzuverwenden . Eine andere wertvolle Sache ist die Zusammensetzung. – Vlad

Verwandte Themen