Saltar al contenido

Componentes reutilizables con React y Redux

Comencemos creando una nueva aplicación de reaccionar usando el CLI de Reaccionar. En tu terminal, genera la aplicación con el siguiente comando:

12$ create-react-app noogle$ cd noogle

bash

Componentes reutilizables con React y Redux
Componentes reutilizables con React y Redux

A continuación añadimos a nuestro proyecto el reductor y el reactivador:

1$ npminstall --save redux react-redux react-router-dom

bash

Una vez hecho, creamos los dos componentes de la página junto con un simple router para navegar por las páginas. Inicializamos el almacén, las acciones y el reductor de redux también. La estructura del directorio para SRCsrc es la siguiente.

12345678910111213src |- componentes |- SearchComponent.js |- páginas |- HomePageComponent.js |- ResultadosPageComponent.js acciones.js App.css App.js index.css index.js reductores.js tienda.js

Para asegurarme de que Noogle se vea increíble, preparé algunas adiciones de CSS. Podrías usarlas o ser creativo. Además, no te olvides de enlazar el bootstrap a index.html también.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263/** índice. css **/body{margin:0;font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif;-webkit-font-smoothing: antialiased;-moz-osx-font-smoothing: grayscale;}code{font-family: source-code-pro, Menlo, Monaco, Consolas, "Courier New", monospace;}. homepage{width:800px;margin-left: auto;margin-right: auto;margin-top:200px;text-align: center;}.homepage h1{margin-bottom:30px;}.homepage input{margin-bottom:15px;}.resultspage{margin-top:50px;}.resultspage.search{margin-bottom:50px;margin-top:20px;}. resultspage input{display: inline-block;width:500px;margin-right:15px;}.resultspage.result{width:800px;border:1px solid #ccc;padding:10px10px10px10px;margin-bottom:10px;}.resultspage.result.title{color:#1a0dab;font-size:20px;}.resultspage.result.url{color:#006621;}

css

Para empezar, vamos a crear un router a nuestra aplicación para facilitar las transiciones de página. Junto con esto, inicializaremos la placa de calderas redux.

123456789101112131415// HomePageComponent.jsimportReact,{Componente}de$0027react$0027;classHomePageComponenteextiendeComponente{render(){return(<divclassName="container "h1;Home Page</h1;</div>)}}exportdefaultHomePageComponent;

jsx

123456789101112131415/// ResultsPageComponent.jsimportReact,{Componente}de$0027react$0027;classResultsPageComponentextendsComponente{render(){return(<divclassName="container"<h1>Results Page</h1></div>)}}exportdefaultResultsPageComponent;

jsx

123456789101112131415/// reductores.jsconst initialState ={}functionsearchReducer(state, action){if(typeof state ===$0027undefined$0027){return initialState }// Creamos un reductor vacío para el estado nowreturn}

jsx

123456// store.jsimport{ createStore }from$0027redux$0027import searchReducer from$0027./reducers$0027const store =createStore(todoApp)

jsx

12345678910111213141516171819202122232425// App.jsimportReactfrom$0027react$0027;import{BrowserRouterasRouter,Route,Link}from "react-router-dom";importHomePageComponentfrom$0027. /pages/HomePageComponent$0027;importResultsPageComponentfrom$0027./pages/ResultsPageComponent$0027;import{Provider}from$0027react-redux$0027import store from$0027. /store$0027;functionApp(){retorno(<Providerstore={store};<Router,div,<Routepath="/"exactcomponent={HomePageComponent}/{HomePageComponent}..; <Routepath="/results "component={ResultsPageComponent}/{{N-Div};}Router{N- Proveedor;);}exportdefaultApp;

jsx

Ahora, ejecute la aplicación con $ npm start y pruebe cómo se ve desde el navegador. Debería mostrar la página de inicio y la página de resultados cuando navegue a http://localhost:3000 y http://localhost:3000/results respectivamente.

Construyendo el componente de búsqueda

El componente de búsqueda consiste en una entrada de texto y un botón. El objetivo del botón es ejecutar un procedimiento de búsqueda utilizando la consulta en la entrada de texto. Primero, creamos el SearchComponent dentro del directorio de componentes. Podríamos usar el directorio de componentes para almacenar los componentes compartidos en la aplicación.

123456789101112131415161718192021222324252627282930313233// SearchComponent.jsimportReact,{Componente}de$0027react$0027;classSearchComponenteextiendeComponente{ state ={ query:""}onInputChange=(e)= &gteste.setState({query: e.target. valor})}onButtonClick=(e)= &gt {//Todo: dispara los procesos de búsqueda}render(){return(<divclassName="search"<inputtype="text "value={this.state. query}onChange={this.onInputChange}/{{N;};buttononClick={this.onButtonClick}{Nbuscar</botón;};}}exportarComponente de búsqueda por defecto;

jsx

En este ejemplo, usamos un patrón de gestión de estado donde el estado de la UI se gestiona internamente – es decir: el estado del campo de entrada se gestiona dentro del componente. Aunque tenemos redux para la gestión de estados, saturar el almacén de redux con estados que no son relevantes para el estado general de la aplicación es un error. Un patrón alternativo sería tener un almacén redux dedicado a la gestión de estados de UI.

Con el componente UI hecho, averigüemos cómo hacer que la búsqueda real funcione.

Haciendo que la búsqueda funcione

Para mantener la guía simple y centrada, no conectaremos ninguna API real a la aplicación. En su lugar, codificaremos algunos valores en nuestra tienda y usaremos un simple filtro de texto para simular un comportamiento de búsqueda. En términos sencillos, tendremos un conjunto fijo de elementos de búsqueda. Una vez que se lanza una consulta, filtraremos los elementos de búsqueda para que coincidan con la consulta. Luego presentamos estos elementos en nuestra vista de resultados. El siguiente código modifica el reductor y las acciones para añadir este comportamiento:

12345678910111213// actions.js// Estas son nuestras acciones typesexportconstSEARCH_LIST="SEARCH_LIST"// Ahora definimos actionsexportfunctionsearchList(query){return{ type:SEARCH_LIST, query }}

jsx

12345678910111213141516171819202122232425262728293031323334353637383940414344454647/// reducers.js import{SEARCH_LIST}from$0027. /actions$0027;const initialState ={ results:[]}// Mock dataconst data =[{"title": "React - A JavaScript library for building user interfaces", "url": "https://reactjs.org/"},{"title": "Tutorial: Intro to React - React", "url": "https://reactjs.org/tutorial/tutorial.html"},{"title": "GitHub - facebook/react: Un declarativo, eficiente y flexible JavaScript", "url": "https://github.com/facebook/react"},{"title": "What is React - W3Schools", "url": "https://www.w3schools.com/whatis/whatis_react. asp"},]exportdefaultfunctionsearchReducer(state, action){if(typeof state ===$0027undefined$0027){return initialState }if(action.type===SEARCH_LIST){const results =[];for(var item of data){if(item.title.indexOf(action.query)!==-1){ results.push(item);}}return{...state, results: results,}}}

jsx

Ahora que la acción de búsqueda está disponible, necesitamos unir esto a nuestro botón de búsqueda dentro del componente de búsqueda. Con eso, nuestro Componente de Búsqueda está completo y, más importante aún, funciona fuera de la caja. Lo que significa que el componente no depende de ningún accesorio del componente principal para funcionar correctamente.

1234567891011121314151617/// SearchComponent.jsimport{ connect }from$0027react-redux$0027;import{ searchList }from$0027../actions$0027;//...onButtonClick=(e)= &gt {this. props.searchList(this.state.query);}//...const mapDispatchToProps ={ searchList,};exportdefaultconnect(null, mapDispatchToProps)(SearchComponent);

jsx

Podemos simplemente añadir el componente de búsqueda tanto al componente de la página de inicio como al componente de la página de resultados y verificar que funciona como se desea. A continuación, construiremos el Componente de la Lista de Resultados.

Construyendo el Componente de la Lista de Resultados

La última pieza de este rompecabezas es mostrar los resultados de la búsqueda en la página de resultados. Para ello, construiremos un componente tonto que acepte una serie de elementos y los muestre. Pero no se le dará la conectividad a la tienda. El componente principal, que es el Componente de la Página de Resultados, se conectaría al almacén y proporcionaría los datos al Componente de la Lista de Resultados. Esto demuestra el segundo tipo de reutilización mientras se utiliza Reducx.

123456789101112131415161718//ResultsListComponent.jsimportReactfrom$0027react$0027;constResultsListComponent=(props)= map((result, index)=>(<divclassName="result "key={index};<divclassName="title"--> {result.title}</div><divclassName="url"--> {result.url}</div></div;))}</div;)}exportdefaultResultsListComponent;

jsx

Actualizaremos el Componente de la Página de Resultados para usar nuestro nuevo y brillante componente y adjuntaremos el almacén para pasar los datos de los resultados según sea necesario.

123456789101112131415161718192021222324/// ResultsPageComponent.jsimportReact, {Component}from$0027react$0027;importResultsListComponentfrom$0027.. /componentes/Lista de resultadosComponente$0027;importar{conectar }de$0027react-redux$0027;claseResultadosPáginaComponenteextiendeComponente{render(){retorno(<divclassName="contenedor "h1 ];Página de resultados</h1 ];<ResultadosLista de resultadosComponentesresultados={esto. props.results}/{{Ndiv};}}mapa de funciónStateToProps(state){retorno{resultados: state.results}}}exportdefaultconnect(mapStateToProps,null)(ResultsPageComponent);

jsx

Redireccionamiento de la ruta con react-redux

Ahora nuestro flamante motor de búsqueda está listo para funcionar; un pequeño problema es que cuando hacemos una búsqueda desde el HomePageComponent, debería redirigirnos a la página de resultados para que veamos los resultados. En la combinación react-redujo, hacer cambios de ruta después de una acción es una situación difícil. Dado que las acciones reducidas deben estar libres de efectos secundarios, es muy recomendable no tener cambios de ruta dentro de ese flujo de datos. En su lugar, usamos varios «hacks». En esta guía mostraré brevemente uno de estos métodos, pero explicaré todos los diferentes métodos en otro momento. Estos cambios en el reductor y en el HomePageComponent proporcionarán la ruta deseada según sea necesario.

1234567891011121314/// ...const initialState ={ resultados:[], hasResultsLoaded:false}///...return{...state, results: results, hasResultsLoaded:true}//...

jsx

123456789101112131415161718192021222324252627282930313233importarReacción,{Componente}de$0027reaccionar$0027;importarBuscarComponentede$0027.. /componentes/Componente de búsqueda$0027;importar{conectar }de$0027react-redux$0027;importar{ conRouter }de "react-router-dom";classHomePageComponente extiendeComponente{deberíaComponenteActualizar(next, prev){si(next.hasResultsLoaded===verdad){esto. props.history.push("/results");returnfalse;}returntrue;}render(){return(<divclassName="container"<h1 ];Home Page</h1 ]};SearchComponent/ </div ];)}}functionmapStateToProps(state){return{ hasResultsLoaded: state. hasResultsLoaded}}exportdefaultconnect(mapStateToProps,null)(withRouter(HomePageComponent));

jsx