import Todo from './Todo.jsx';
const mapStateToProps = (state, ownProps) => {
return {
todo: state.todos[ownProps.id],
}
}
export default connect(mapStateToProps, null)(Todo);
const mapStateToProps = function mapStateToProps(state) {
return state;
}
Estamos retornando todo el objeto state
class App extends React.Component {
componentWillMount() {
this.props.getUser(this.props.locationBeforeTransitions.pathname);
}
render() {
return (
<DocumentTitle title={Translations.PAGE_TITLE_DEFAULT}>
<TransitionManager showSpinner={this.props.login.isFetchingUserFromToken}>
{ this.props.children }
</TransitionManager>
</DocumentTitle>
);
}
}
Y luego tenemos que buscar las propiedades que precisamos.
- retornar sólo lo que el componente necesita
const mapStateToProps = function mapStateToProps(state) {
const pathname = state.route.locationBeforeTransitions.pathname;
const isFetchingUserFromToken = state.login.isFetchingUserFromToken;
return { pathname, isFetchingUserFromToken }
}
class App extends React.Component {
componentWillMount() {
this.props.getUser(this.props.pathname);
}
render() {
return (
<DocumentTitle title={Translations.PAGE_TITLE_DEFAULT}>
<TransitionManager showSpinner={this.props.isFetchingUserFromToken}>
{ this.props.children }
</TransitionManager>
</DocumentTitle>
);
}
}
La interfaz del componente queda mucho más clara y definida
class App extends React.Component {
propTypes = {
children: React.PropTypes.object,
getUser: React.PropTypes.func,
isFetchingUserFromToken: React.PropTypes.bool,
pathName: React.PropTypes.string,
}
/*** Codigo del componente ***/
};
const mapStateToProps = function mapStateToProps(state) {
const pathname = state.route.locationBeforeTransitions.pathname;
const isFetchingUserFromToken = state.login.isFetchingUserFromToken;
return { pathname, isFetchingUserFromToken };
}
const mapStateToProps = function mapStateToProps(state) {
return state
}
[
{
"_id": "5909e202bfc1e6d2ce07e931",
"index": 0,
"guid": "c7c6eb56-176b-4c95-8ada-f6dff11cea95",
"isActive": false,
"balance": "$1,426.78",
"picture": "http://placehold.it/32x32",
"age": 21,
"eyeColor": "green",
"name": "Rivers Ellison",
"gender": "male",
"company": "ISOLOGIX",
"email": "riversellison@isologix.com",
"phone": "+1 (907) 534-3406",
"address": "677 Grace Court, Canby, Connecticut, 600",
"about": "Sunt dolore occaecat veniam deserunt dolor officia. Ea aliqua sunt cupidatat ut laborum sunt nostrud adipisicing fugiat pariatur. Id mollit ipsum sint enim et. Laboris veniam dolore pariatur exercitation laborum anim dolore. Irure officia ex aliqua labore ea proident aute sunt nulla. Anim ex deserunt anim deserunt laborum est laborum labore cillum occaecat voluptate in aliquip.\r\n",
"registered": "2015-02-16T04:38:44 +03:00",
"latitude": -23.818232,
"longitude": 101.703476,
"tags": [
"eu",
"anim",
"deserunt",
"duis",
"amet",
"sit",
"pariatur"
],
"friends": [
{
"id": 0,
"name": "Parrish Villarreal"
},
{
"id": 1,
"name": "Betsy Mueller"
},
{
"id": 2,
"name": "Peck Salazar"
}
],
"greeting": "Hello, Rivers Ellison! You have 5 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "5909e2020ee0c00c5bd23942",
"index": 1,
"guid": "bcc55d66-66cf-4993-82b1-f7df8de8bc0d",
"isActive": true,
"balance": "$1,083.59",
"picture": "http://placehold.it/32x32",
"age": 32,
"eyeColor": "brown",
"name": "Hyde Snow",
"gender": "male",
"company": "STUCCO",
"email": "hydesnow@stucco.com",
"phone": "+1 (898) 517-2958",
"address": "982 Neptune Court, Kylertown, New York, 8396",
"about": "Et ipsum non cillum enim reprehenderit nisi minim pariatur esse. Minim ullamco tempor excepteur ad sint commodo esse et id non eu eu. Ex et mollit veniam ad. Irure do magna excepteur consectetur eu cillum adipisicing reprehenderit do. Ex ea voluptate enim est ad magna reprehenderit consequat mollit esse tempor.\r\n",
"registered": "2014-08-11T05:08:14 +03:00",
"latitude": -45.554253,
"longitude": 24.409109,
"tags": [
"laborum",
"fugiat",
"enim",
"aliqua",
"fugiat",
"irure",
"tempor"
],
"friends": [
{
"id": 0,
"name": "Jacobs Shannon"
},
{
"id": 1,
"name": "Jan Pena"
},
{
"id": 2,
"name": "Sallie Hamilton"
}
],
"greeting": "Hello, Hyde Snow! You have 10 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "5909e202abba6f2e7b1d6fdd",
"index": 2,
"guid": "54f40bef-54a1-4ab5-82e6-adce37226e68",
"isActive": false,
"balance": "$3,417.90",
"picture": "http://placehold.it/32x32",
"age": 28,
"eyeColor": "blue",
"name": "Merritt Bray",
"gender": "male",
"company": "UPLINX",
"email": "merrittbray@uplinx.com",
"phone": "+1 (840) 540-2695",
"address": "529 Tapscott Street, Movico, Idaho, 954",
"about": "In ad nisi reprehenderit esse commodo. Culpa ullamco ipsum enim voluptate labore consectetur amet esse et aliqua et. Nisi mollit sunt incididunt incididunt aliqua ipsum elit. Velit cupidatat velit est amet aliquip anim commodo amet minim dolore enim. Cupidatat sit adipisicing ullamco consequat tempor id in dolor eiusmod aliqua cillum est ullamco. Pariatur enim qui ad dolor officia laboris adipisicing in ea ut esse.\r\n",
"registered": "2014-07-03T11:19:57 +03:00",
"latitude": 24.491741,
"longitude": -145.470934,
"tags": [
"deserunt",
"sint",
"eiusmod",
"amet",
"irure",
"nulla",
"Lorem"
],
"friends": [
{
"id": 0,
"name": "Eleanor Delacruz"
},
{
"id": 1,
"name": "Turner Gross"
},
{
"id": 2,
"name": "Finch Mcneil"
}
],
"greeting": "Hello, Merritt Bray! You have 5 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "5909e20225e7ebac44e2d200",
"index": 3,
"guid": "1cdde354-6781-4ec0-bc49-33e9778e3313",
"isActive": false,
"balance": "$3,631.47",
"picture": "http://placehold.it/32x32",
"age": 38,
"eyeColor": "green",
"name": "Mcfarland Melton",
"gender": "male",
"company": "ASSISTIX",
"email": "mcfarlandmelton@assistix.com",
"phone": "+1 (841) 404-2770",
"address": "525 Royce Street, Lewis, Tennessee, 7008",
"about": "Laborum tempor officia sit consectetur voluptate deserunt et dolore sunt sit consectetur officia deserunt. Veniam amet sit eiusmod officia. Do sint ad fugiat sint deserunt reprehenderit aute irure. Dolore culpa non cupidatat in aute mollit. Et irure ut pariatur nisi sunt.\r\n",
"registered": "2014-01-06T06:24:48 +03:00",
"latitude": 85.011245,
"longitude": 168.285699,
"tags": [
"sint",
"aliqua",
"sint",
"officia",
"laborum",
"occaecat",
"officia"
],
"friends": [
{
"id": 0,
"name": "Grimes Holder"
},
{
"id": 1,
"name": "Marlene Hardy"
},
{
"id": 2,
"name": "Juliette Hines"
}
],
"greeting": "Hello, Mcfarland Melton! You have 10 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "5909e20212221cccf0809b8e",
"index": 4,
"guid": "fa43fc9e-cd11-42f9-98f3-cd6252b2cb2e",
"isActive": false,
"balance": "$2,045.81",
"picture": "http://placehold.it/32x32",
"age": 34,
"eyeColor": "blue",
"name": "Raquel Drake",
"gender": "female",
"company": "FURNAFIX",
"email": "raqueldrake@furnafix.com",
"phone": "+1 (954) 543-3334",
"address": "588 Kenilworth Place, Smock, Hawaii, 6260",
"about": "Sit irure minim consectetur eu. Non quis Lorem duis pariatur. Reprehenderit magna in voluptate anim.\r\n",
"registered": "2017-04-04T07:44:44 +03:00",
"latitude": 87.95867,
"longitude": -64.982767,
"tags": [
"proident",
"ad",
"sit",
"culpa",
"id",
"dolore",
"nisi"
],
"friends": [
{
"id": 0,
"name": "Constance Mcgowan"
},
{
"id": 1,
"name": "Marsha Becker"
},
{
"id": 2,
"name": "Tracey Kinney"
}
],
"greeting": "Hello, Raquel Drake! You have 4 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "5909e202f9e951a59069b6f5",
"index": 5,
"guid": "290617f8-c0f4-47ac-a162-c2f0d25f6c3f",
"isActive": true,
"balance": "$1,845.49",
"picture": "http://placehold.it/32x32",
"age": 27,
"eyeColor": "green",
"name": "Petty Mccall",
"gender": "male",
"company": "ZILLACOM",
"email": "pettymccall@zillacom.com",
"phone": "+1 (990) 553-2406",
"address": "210 Colin Place, Biddle, Alabama, 697",
"about": "Consectetur amet irure sit nisi quis magna eu nostrud aliquip. Do minim duis tempor id irure amet occaecat. Commodo elit exercitation ea ad anim deserunt voluptate sit qui pariatur exercitation velit occaecat. Pariatur cillum id occaecat esse. Ipsum sit non culpa dolor.\r\n",
"registered": "2015-02-01T04:51:30 +03:00",
"latitude": 39.788631,
"longitude": -119.798066,
"tags": [
"incididunt",
"pariatur",
"commodo",
"proident",
"mollit",
"culpa",
"fugiat"
],
"friends": [
{
"id": 0,
"name": "Mitzi Reyes"
},
{
"id": 1,
"name": "Ava Best"
},
{
"id": 2,
"name": "Celeste Weber"
}
],
"greeting": "Hello, Petty Mccall! You have 5 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "5909e20245a110dbfba5553c",
"index": 6,
"guid": "2ece983f-af14-4cf5-a8d0-b1cebe470f19",
"isActive": false,
"balance": "$2,377.02",
"picture": "http://placehold.it/32x32",
"age": 25,
"eyeColor": "green",
"name": "Laurie Valdez",
"gender": "female",
"company": "AQUAFIRE",
"email": "laurievaldez@aquafire.com",
"phone": "+1 (949) 498-2402",
"address": "569 Hampton Avenue, Fairfield, Maryland, 684",
"about": "Minim magna dolore officia velit exercitation magna aliquip labore. Cupidatat Lorem aliqua cillum quis voluptate exercitation sint. In dolor velit sunt sit commodo officia anim nisi qui excepteur pariatur.\r\n",
"registered": "2015-04-06T11:12:55 +03:00",
"latitude": 5.557238,
"longitude": 102.973884,
"tags": [
"est",
"cillum",
"ea",
"pariatur",
"amet",
"sunt",
"nisi"
],
"friends": [
{
"id": 0,
"name": "Vega Talley"
},
{
"id": 1,
"name": "Susie Holden"
},
{
"id": 2,
"name": "Krista Nolan"
}
],
"greeting": "Hello, Laurie Valdez! You have 2 unread messages.",
"favoriteFruit": "banana"
}
]
{
"pathname": "/sandbox",
"isFetchingUserFromToken": true,
}
const getPersonStats = (person) => {
const stats = expensiveFunction(person);
const children = person.children ?
person.children.map(getPersonStats) : [];
return {
stats,
children,
};
}
const getFamilyStats = (state) => state.familyPersons.map(getPersonStats);
const mapStateToProps = (state) => ({
getFamilyTree: getFamilyStats(state),
});
connect(mapStateToProps)(FamilyTreeRecursiveComponent)
import { createSelector } from 'reselect';
const getPersonStats = (person) => {
const stats = expensiveFunction(person);
const children = person.children ?
person.children.map(getPersonStats) : [];
return {
stats,
children,
};
}
const getFamilyPersons = (state, familyId) => state.familyPersons[familyId];
const getFamilyStats = createSelector(
getFamilyPersons,
(persons) => persons.map(getPersonStats)
);
const mapStateToProps = (state, props) => ({
getFamilyTree: getFamilyStats(state, props.familyId),
});
connect(mapStateToProps)(FamilyTreeRecursiveComponent)
import { getFamilyStats } from './FamilyTree.selector.js'
const mapStateToProps = (state, props) => ({
getFamilyTree: getFamilyStats(state, props.familyId),
});
connect(mapStateToProps)(FamilyTreeRecursiveComponent)
const makeGetFamilyStats = () => createSelector(
getFamilyPersons,
(persons) => persons.map(getPersonStats)
);
const makeMapStateToProps = () => {
const getFamilyStats = makeGetFamilyStats();
const mapStateToProps = (state, props) => ({
getFamilyTree: getFamilyStats(state, props.familyId),
});
return mapStateToProps;
};
connect(makeMapStateToProps)(FamilyTreeRecursiveComponent)
React.Component
, extendemos de React.PureComponent
class ChildComponent extends React.Component {
render() {
return <span>{this.props.text}</span>;
}
}
class ChildPureComponent extends React.PureComponent {
render() {
return <span>{this.props.text}</span>;
}
}
class ParentComponent extends React.Component {
render() {
this.state.text = 'hello';
setInterval(() => this.setState({text: 'hello'}), 1000)
}
render() {
return (
<ChildComponent text={this.state.text} />
<ChildPureComponent text={this.state.text} />
);
}
}
class GridToolbar extends React.Component {
shouldComponentUpdate() {
return false;
}
render() {
return (
<OptionsPanel>
{ this.props.toolbar }
{ this.props.displayOptions }
</OptionsPanel>
);
}
}
GridToolbar.propTypes = {
toolbar: React.PropTypes.node,
displayOptions: React.PropTypes.node.isRequired,
};
GridToolbar.defaultProps = {
toolbar: <Toolbar />,
displayOptions: <DisplayOptions />,
};
render() {
if (this.state.someCondition) return null;
return (
<div>
<MyComplexChild />
<MySecondComplexChild />
</div>
);
}
render() {
return (
<div>
<MyChild
items={this.props.items || []}
handleChange={(val) => this.someValue = val;}
handleSomething={handleSomething.bind(this)}
/>
</div>
);
}
class MyComponent extends React.Component {
handleChange = (val) => this.someValue = val
handleSomething = ({ text }) => this.props.someCallback(text)
render() {
return (
<div>
<MyChild
items={this.props.items}
handleChange={handleChange}
handleSomething={handleSomething}
/>
</div>
);
}
}
MyComponent.defaultProps = {
items: [],
};
<ul>
<li>yasten</li>
<li>danee</li>
</ul>
<ul>
<li>yasten</li>
<li>danee</li>
<li>matse</li>
</ul>
<ul>
<li>yasten</li>
<li>danee</li>
</ul>
<ul>
<li>matse</li>
<li>yasten</li>
<li>danee</li>
</ul>
<ul>
<li key="puyo">yasten</li>
<li key="mata">danee</li>
</ul>
<ul>
<li key="cesp">matse</li>
<li key="puyo">yasten</li>
<li key="mata">danee</li>
</ul>
npm install --save-dev react-perf-addons
Perf.printInclusive();
Perf.printExclusive();
Perf.printWasted();
mapStateToProps
pura, precisa e inteligente. Si es necesario, HOF
PureComponent
srender
's que no creen nuevos objetos