├── .eslintrc ├── .gitignore ├── .prettierrc ├── README.md ├── package-lock.json ├── package.json ├── public ├── cover.png ├── favicon.ico ├── index.html ├── logo192.png ├── logo512.png ├── manifest.json └── robots.txt ├── src ├── App.js ├── components │ ├── app-router.js │ ├── layout.js │ └── welcome-page.js ├── compound-component │ ├── components │ │ └── compound-component-page.js │ └── index.js ├── control-props │ ├── components │ │ └── control-props-page.js │ └── index.js ├── custom-hook │ ├── components │ │ └── custom-hook-page.js │ └── index.js ├── extensible-styles │ ├── components │ │ └── extensible-styles-page.js │ └── index.js ├── hoc │ ├── components │ │ └── hoc-page.js │ └── index.js ├── index.js ├── props-getters │ ├── components │ │ └── props-getters-page.js │ └── index.js ├── render-props │ ├── components │ │ └── render-props-page.js │ └── index.js ├── reportWebVitals.js ├── routes.js ├── setupTests.js ├── state-initializer │ ├── components │ │ └── state-initializer-page.js │ └── index.js └── state-reducer │ ├── components │ └── state-reducer-page.js │ └── index.js └── yarn.lock /.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": [ 3 | "react-app", 4 | "plugin:jsx-a11y/recommended", 5 | "prettier", 6 | "prettier/react", 7 | "eslint-config-prettier" 8 | ], 9 | "plugins": ["jsx-a11y", "prettier"], 10 | "rules": { 11 | "react/jsx-filename-extension": [1, {"extensions": [".js"]}], 12 | "semi": [2, "always"] 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | .eslintcache 26 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "arrowParens": "avoid", 3 | "bracketSpacing": false, 4 | "htmlWhitespaceSensitivity": "css", 5 | "insertPragma": false, 6 | "jsxBracketSameLine": false, 7 | "jsxSingleQuote": false, 8 | "printWidth": 80, 9 | "proseWrap": "always", 10 | "quoteProps": "as-needed", 11 | "requirePragma": false, 12 | "semi": true, 13 | "singleQuote": true, 14 | "tabWidth": 2, 15 | "trailingComma": "all", 16 | "useTabs": false 17 | } 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Patrones Avanzados en React JS 2 | 3 | [](https://www.udemy.com/course/react-js-patrones/?referralCode=FF3F91AFC79C5837D13E) 4 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-patterns", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@material-ui/core": "4.11.2", 7 | "@material-ui/icons": "4.11.2", 8 | "@testing-library/jest-dom": "^5.11.4", 9 | "@testing-library/react": "^11.1.0", 10 | "@testing-library/user-event": "^12.1.10", 11 | "react": "^17.0.1", 12 | "react-dom": "^17.0.1", 13 | "react-router-dom": "5.2.0", 14 | "react-scripts": "4.0.1", 15 | "web-vitals": "^0.2.4" 16 | }, 17 | "scripts": { 18 | "start": "react-scripts start", 19 | "build": "react-scripts build", 20 | "test": "react-scripts test", 21 | "eject": "react-scripts eject", 22 | "lint": "eslint --ignore-path .gitignore .", 23 | "format": "prettier --ignore-path .gitignore --write \"**/*.+(js)\"" 24 | }, 25 | "browserslist": { 26 | "production": [ 27 | ">0.2%", 28 | "not dead", 29 | "not op_mini all" 30 | ], 31 | "development": [ 32 | "last 1 chrome version", 33 | "last 1 firefox version", 34 | "last 1 safari version" 35 | ] 36 | }, 37 | "devDependencies": { 38 | "eslint-config-prettier": "7.1.0", 39 | "eslint-plugin-jsx-a11y": "6.4.1", 40 | "eslint-plugin-prettier": "3.3.0", 41 | "prettier": "2.2.1", 42 | "typescript": "4.1.3" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /public/cover.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Developero-oficial/react-patterns/0e5f61e103b423a7a949160c27734ad5b0082b34/public/cover.png -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Developero-oficial/react-patterns/0e5f61e103b423a7a949160c27734ad5b0082b34/public/favicon.ico -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 12 | 13 | 17 | 18 | 27 | React App 28 | 29 | 30 | 31 |
32 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /public/logo192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Developero-oficial/react-patterns/0e5f61e103b423a7a949160c27734ad5b0082b34/public/logo192.png -------------------------------------------------------------------------------- /public/logo512.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Developero-oficial/react-patterns/0e5f61e103b423a7a949160c27734ad5b0082b34/public/logo512.png -------------------------------------------------------------------------------- /public/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "short_name": "React App", 3 | "name": "Create React App Sample", 4 | "icons": [ 5 | { 6 | "src": "favicon.ico", 7 | "sizes": "64x64 32x32 24x24 16x16", 8 | "type": "image/x-icon" 9 | }, 10 | { 11 | "src": "logo192.png", 12 | "type": "image/png", 13 | "sizes": "192x192" 14 | }, 15 | { 16 | "src": "logo512.png", 17 | "type": "image/png", 18 | "sizes": "512x512" 19 | } 20 | ], 21 | "start_url": ".", 22 | "display": "standalone", 23 | "theme_color": "#000000", 24 | "background_color": "#ffffff" 25 | } 26 | -------------------------------------------------------------------------------- /public/robots.txt: -------------------------------------------------------------------------------- 1 | # https://www.robotstxt.org/robotstxt.html 2 | User-agent: * 3 | Disallow: 4 | -------------------------------------------------------------------------------- /src/App.js: -------------------------------------------------------------------------------- 1 | import {BrowserRouter as Router} from 'react-router-dom'; 2 | 3 | import {AppRouter} from './components/app-router'; 4 | import {Layout} from './components/layout'; 5 | 6 | function App() { 7 | return ( 8 | 9 | 10 | 11 | 12 | 13 | ); 14 | } 15 | 16 | export default App; 17 | -------------------------------------------------------------------------------- /src/components/app-router.js: -------------------------------------------------------------------------------- 1 | import {Route, Switch} from 'react-router-dom'; 2 | import {routes} from '../routes'; 3 | 4 | export const AppRouter = () => ( 5 | 6 | {routes.map(({path, Component, exact = false}) => ( 7 | 8 | ))} 9 | 10 | ); 11 | -------------------------------------------------------------------------------- /src/components/layout.js: -------------------------------------------------------------------------------- 1 | import React, {useState} from 'react'; 2 | import {Link} from 'react-router-dom'; 3 | import {makeStyles} from '@material-ui/core/styles'; 4 | import CssBaseline from '@material-ui/core/CssBaseline'; 5 | import Drawer from '@material-ui/core/Drawer'; 6 | import AppBar from '@material-ui/core/AppBar'; 7 | import Toolbar from '@material-ui/core/Toolbar'; 8 | import List from '@material-ui/core/List'; 9 | import Typography from '@material-ui/core/Typography'; 10 | import Divider from '@material-ui/core/Divider'; 11 | import IconButton from '@material-ui/core/IconButton'; 12 | import Container from '@material-ui/core/Container'; 13 | import MenuIcon from '@material-ui/icons/Menu'; 14 | import ChevronLeftIcon from '@material-ui/icons/ChevronLeft'; 15 | import ListItem from '@material-ui/core/ListItem'; 16 | import ListItemText from '@material-ui/core/ListItemText'; 17 | import PropTypes from 'prop-types'; 18 | 19 | import {routes} from '../routes'; 20 | 21 | const drawerWidth = 240; 22 | 23 | const useStyles = makeStyles(theme => ({ 24 | root: { 25 | display: 'flex', 26 | }, 27 | toolbar: { 28 | paddingRight: 24, 29 | }, 30 | toolbarIcon: { 31 | display: 'flex', 32 | alignItems: 'center', 33 | justifyContent: 'flex-end', 34 | padding: '0 8px', 35 | ...theme.mixins.toolbar, 36 | }, 37 | appBar: { 38 | zIndex: theme.zIndex.drawer + 1, 39 | transition: theme.transitions.create(['width', 'margin'], { 40 | easing: theme.transitions.easing.sharp, 41 | duration: theme.transitions.duration.leavingScreen, 42 | }), 43 | }, 44 | appBarShift: { 45 | marginLeft: drawerWidth, 46 | width: `calc(100% - ${drawerWidth}px)`, 47 | transition: theme.transitions.create(['width', 'margin'], { 48 | easing: theme.transitions.easing.sharp, 49 | duration: theme.transitions.duration.enteringScreen, 50 | }), 51 | }, 52 | menuButton: { 53 | marginRight: 36, 54 | }, 55 | menuButtonHidden: { 56 | display: 'none', 57 | }, 58 | title: { 59 | flexGrow: 1, 60 | }, 61 | drawerPaper: { 62 | position: 'relative', 63 | whiteSpace: 'nowrap', 64 | width: drawerWidth, 65 | transition: theme.transitions.create('width', { 66 | easing: theme.transitions.easing.sharp, 67 | duration: theme.transitions.duration.enteringScreen, 68 | }), 69 | }, 70 | drawerPaperClose: { 71 | overflowX: 'hidden', 72 | transition: theme.transitions.create('width', { 73 | easing: theme.transitions.easing.sharp, 74 | duration: theme.transitions.duration.leavingScreen, 75 | }), 76 | width: 0, 77 | }, 78 | appBarSpacer: theme.mixins.toolbar, 79 | content: { 80 | flexGrow: 1, 81 | height: '100vh', 82 | overflow: 'auto', 83 | }, 84 | container: { 85 | paddingTop: theme.spacing(4), 86 | paddingBottom: theme.spacing(4), 87 | }, 88 | })); 89 | 90 | export const Layout = ({children}) => { 91 | const classes = useStyles(); 92 | const [open, setOpen] = useState(false); 93 | 94 | const handleDrawerOpen = () => { 95 | setOpen(true); 96 | }; 97 | 98 | const handleDrawerClose = () => { 99 | setOpen(false); 100 | }; 101 | 102 | return ( 103 |
104 | 105 | 109 | 110 | 119 | 120 | 121 | 128 | Guía definitiva: Aprende los 9 Patrones Avanzados en ReactJS 129 | 130 | 131 | 132 | 139 |
140 | 141 | 142 | 143 |
144 | 145 | 146 |
147 | {routes.map(({path, label}) => ( 148 | 149 | 150 | 151 | ))} 152 |
153 |
154 |
155 |
156 | 157 |
158 | {children} 159 | 160 |
161 |
162 | ); 163 | }; 164 | 165 | Layout.propTypes = { 166 | children: PropTypes.node.isRequired, 167 | }; 168 | -------------------------------------------------------------------------------- /src/components/welcome-page.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Typography from '@material-ui/core/Typography'; 3 | 4 | export const WelcomePage = () => ( 5 | <> 6 | 7 | ¡Hola Mundo! 8 | 9 | 10 | 11 | Esta aplicación forma parte del curso Guía definitiva: Aprende los 9 12 | Patrones Avanzados en ReactJS 13 | 14 | 15 | ); 16 | -------------------------------------------------------------------------------- /src/compound-component/components/compound-component-page.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const CompoundComponentPage = () => ( 4 | <> 5 |

Compound Component

6 |

Sigue las instrucciones que vienen en el curso.

7 | 8 | ); 9 | -------------------------------------------------------------------------------- /src/compound-component/index.js: -------------------------------------------------------------------------------- 1 | import {CompoundComponentPage} from './components/compound-component-page'; 2 | 3 | export {CompoundComponentPage}; 4 | -------------------------------------------------------------------------------- /src/control-props/components/control-props-page.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const ControlPropsPage = () => ( 4 | <> 5 |

Control Props

6 |

Sigue las instrucciones que vienen en el curso.

7 | 8 | ); 9 | -------------------------------------------------------------------------------- /src/control-props/index.js: -------------------------------------------------------------------------------- 1 | import {ControlPropsPage} from './components/control-props-page'; 2 | 3 | export {ControlPropsPage}; 4 | -------------------------------------------------------------------------------- /src/custom-hook/components/custom-hook-page.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const CustomHookPage = () => ( 4 | <> 5 |

Custom Hook

6 |

Sigue las instrucciones que vienen en el curso.

7 | 8 | ); 9 | -------------------------------------------------------------------------------- /src/custom-hook/index.js: -------------------------------------------------------------------------------- 1 | import {CustomHookPage} from './components/custom-hook-page'; 2 | 3 | export {CustomHookPage}; 4 | -------------------------------------------------------------------------------- /src/extensible-styles/components/extensible-styles-page.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const ExtensibleStylesPage = () => ( 4 | <> 5 |

Extensible Styles

6 |

Sigue las instrucciones que vienen en el curso.

7 | 8 | ); 9 | -------------------------------------------------------------------------------- /src/extensible-styles/index.js: -------------------------------------------------------------------------------- 1 | import {ExtensibleStylesPage} from './components/extensible-styles-page'; 2 | 3 | export {ExtensibleStylesPage}; 4 | -------------------------------------------------------------------------------- /src/hoc/components/hoc-page.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const HocPage = () => ( 4 | <> 5 |

High Order Component (HOC)

6 |

Sigue las instrucciones que vienen en el curso.

7 | 8 | ); 9 | -------------------------------------------------------------------------------- /src/hoc/index.js: -------------------------------------------------------------------------------- 1 | import {HocPage} from './components/hoc-page'; 2 | 3 | export {HocPage}; 4 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import ReactDOM from 'react-dom'; 3 | 4 | import App from './App'; 5 | import reportWebVitals from './reportWebVitals'; 6 | 7 | ReactDOM.render( 8 | 9 | 10 | , 11 | document.getElementById('root'), 12 | ); 13 | 14 | // If you want to start measuring performance in your app, pass a function 15 | // to log results (for example: reportWebVitals(console.log)) 16 | // or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals 17 | reportWebVitals(); 18 | -------------------------------------------------------------------------------- /src/props-getters/components/props-getters-page.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const PropsGettersPage = () => ( 4 | <> 5 |

Props Getters

6 |

Sigue las instrucciones que vienen en el curso.

7 | 8 | ); 9 | -------------------------------------------------------------------------------- /src/props-getters/index.js: -------------------------------------------------------------------------------- 1 | import {PropsGettersPage} from './components/props-getters-page'; 2 | 3 | export {PropsGettersPage}; 4 | -------------------------------------------------------------------------------- /src/render-props/components/render-props-page.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const RenderPropsPage = () => ( 4 | <> 5 |

Render Props

6 |

Sigue las instrucciones que vienen en el curso.

7 | 8 | ); 9 | -------------------------------------------------------------------------------- /src/render-props/index.js: -------------------------------------------------------------------------------- 1 | import {RenderPropsPage} from './components/render-props-page'; 2 | 3 | export {RenderPropsPage}; 4 | -------------------------------------------------------------------------------- /src/reportWebVitals.js: -------------------------------------------------------------------------------- 1 | const reportWebVitals = onPerfEntry => { 2 | if (onPerfEntry && onPerfEntry instanceof Function) { 3 | import('web-vitals').then(({getCLS, getFID, getFCP, getLCP, getTTFB}) => { 4 | getCLS(onPerfEntry); 5 | getFID(onPerfEntry); 6 | getFCP(onPerfEntry); 7 | getLCP(onPerfEntry); 8 | getTTFB(onPerfEntry); 9 | }); 10 | } 11 | }; 12 | 13 | export default reportWebVitals; 14 | -------------------------------------------------------------------------------- /src/routes.js: -------------------------------------------------------------------------------- 1 | import {CustomHookPage} from './custom-hook'; 2 | import {HocPage} from './hoc'; 3 | import {ExtensibleStylesPage} from './extensible-styles'; 4 | import {CompoundComponentPage} from './compound-component'; 5 | import {RenderPropsPage} from './render-props'; 6 | import {ControlPropsPage} from './control-props'; 7 | import {PropsGettersPage} from './props-getters'; 8 | import {StateInitializerPage} from './state-initializer'; 9 | import {StateReducerPage} from './state-reducer'; 10 | import {WelcomePage} from './components/welcome-page'; 11 | 12 | export const routes = [ 13 | { 14 | path: '/', 15 | label: 'Bienvenida', 16 | Component: WelcomePage, 17 | exact: true, 18 | }, 19 | { 20 | path: '/custom-hook', 21 | label: 'Custom Hooks', 22 | Component: CustomHookPage, 23 | }, 24 | { 25 | path: '/hoc', 26 | label: 'HOC', 27 | Component: HocPage, 28 | }, 29 | { 30 | path: '/extensible-styles', 31 | label: 'Extensible Styles', 32 | Component: ExtensibleStylesPage, 33 | }, 34 | { 35 | path: '/compound-components', 36 | label: 'Compound Components', 37 | Component: CompoundComponentPage, 38 | }, 39 | { 40 | path: '/render-props', 41 | label: 'Render Props', 42 | Component: RenderPropsPage, 43 | }, 44 | { 45 | path: '/control-props', 46 | label: 'Control Props', 47 | Component: ControlPropsPage, 48 | }, 49 | { 50 | path: '/props-getters', 51 | label: 'Props Getters', 52 | Component: PropsGettersPage, 53 | }, 54 | { 55 | path: '/state-initializer', 56 | label: 'State Initializer', 57 | Component: StateInitializerPage, 58 | }, 59 | { 60 | path: '/state-reducer', 61 | label: 'State Reducer', 62 | Component: StateReducerPage, 63 | }, 64 | ]; 65 | -------------------------------------------------------------------------------- /src/setupTests.js: -------------------------------------------------------------------------------- 1 | // jest-dom adds custom jest matchers for asserting on DOM nodes. 2 | // allows you to do things like: 3 | // expect(element).toHaveTextContent(/react/i) 4 | // learn more: https://github.com/testing-library/jest-dom 5 | import '@testing-library/jest-dom'; 6 | -------------------------------------------------------------------------------- /src/state-initializer/components/state-initializer-page.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const StateInitializerPage = () => ( 4 | <> 5 |

State Initializer

6 |

Sigue las instrucciones que vienen en el curso.

7 | 8 | ); 9 | -------------------------------------------------------------------------------- /src/state-initializer/index.js: -------------------------------------------------------------------------------- 1 | import {StateInitializerPage} from './components/state-initializer-page'; 2 | 3 | export {StateInitializerPage}; 4 | -------------------------------------------------------------------------------- /src/state-reducer/components/state-reducer-page.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | 3 | export const StateReducerPage = () => ( 4 | <> 5 |

State Reducer

6 |

Sigue las instrucciones que vienen en el curso.

7 | 8 | ); 9 | -------------------------------------------------------------------------------- /src/state-reducer/index.js: -------------------------------------------------------------------------------- 1 | import {StateReducerPage} from './components/state-reducer-page'; 2 | 3 | export {StateReducerPage}; 4 | --------------------------------------------------------------------------------