<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Lestley Gabo</title>
    <description>The latest articles on Forem by Lestley Gabo (@lestgabo).</description>
    <link>https://forem.com/lestgabo</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F120450%2Fab69e29e-1964-412d-8989-d0f3302f8f2c.jpeg</url>
      <title>Forem: Lestley Gabo</title>
      <link>https://forem.com/lestgabo</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/lestgabo"/>
    <language>en</language>
    <item>
      <title>How to make a user friendly select when using React, Redux, and Firebase (Part 2) - Get real data</title>
      <dc:creator>Lestley Gabo</dc:creator>
      <pubDate>Thu, 30 Jan 2020 08:53:30 +0000</pubDate>
      <link>https://forem.com/lestgabo/how-to-make-a-user-friendly-select-when-using-react-redux-and-firebase-part-2-get-real-data-2b7n</link>
      <guid>https://forem.com/lestgabo/how-to-make-a-user-friendly-select-when-using-react-redux-and-firebase-part-2-get-real-data-2b7n</guid>
      <description>&lt;p&gt;&lt;b&gt;This will be impossible to follow if you don't have Redux set up.&lt;/b&gt;&lt;/p&gt;

&lt;p&gt;I use data from &lt;a href="https://www.communitydragon.org/" rel="noopener noreferrer"&gt;CDragon&lt;/a&gt;. They parse and serve League of Legends (LoL) assets into APIs. They are almost always up to date and have an active community and is probably the easiest way to get LoL assets.&lt;/p&gt;

&lt;p&gt;How I call the CDragon API:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;I have a component &lt;code&gt;&amp;lt;InitData /&amp;gt;&lt;/code&gt;, and it's called inside App.js.&lt;/li&gt;
&lt;li&gt;I keep it simple and bypass CORS issues by using a proxy. I am sure using &lt;code&gt;fetch&lt;/code&gt; you can skip the proxy but I don't want to fix what isn't broken.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// InitData.js
import React from 'react';
import axios from 'axios';
import { connect } from 'react-redux';

import { getDataCDragon } from '../../store/actions/GetData';
const PROXY_URL = 'https://cors-anywhere.herokuapp.com/';
const API_URL_CDRAGON = 'https://raw.communitydragon.org/latest/cdragon/tft/en_us.json';
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;I then parse the data inside &lt;code&gt;componentDidMount(){}&lt;/code&gt; to make sure the data is taken before the render.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// InitData.js
 componentDidMount() {
        let cDragonData = axios({
            method: 'get',
            url: PROXY_URL + API_URL_CDRAGON,
            responseType: 'json',
            crossdomain: true
        });

        Promise.all([cDragonData])
            .then(values =&amp;gt; {
                let itemsData = values[0].data.items;

           // filter out hex items
                itemsData = itemsData.filter(itemData =&amp;gt; itemData.id &amp;gt; 0 &amp;amp;&amp;amp; itemData.id &amp;lt; 9000);

                tftData = {
                    itemsData: itemsData,
                };

                // calls action getData
                this.props.getDataCDragon(tftData);
            })
            .catch(err =&amp;gt; {
                console.log('fetch data error', err);
                this.setState({ isFailed: true });
            });
    }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Used axios to promise the data. Did a lot of console logging to see what kind of data I was getting, i.e. objects vs arrays. &lt;/li&gt;
&lt;li&gt;I am familiar with the JSON data from the CDragon API and so I know how to filter the items data. (-) IDs are old or unused, (&amp;gt; 9000) IDs are hexes.&lt;/li&gt;
&lt;li&gt;The important part is itemData being packaged into an object. (It's funny looking, but keep in mind I parsed more than just itemsData)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;this.props.getDataCDragon(tftData);&lt;/code&gt; is an action that will save itemsData into the Redux store (just store from now on).
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// InitData.js
const mapDispatchToProps = dispatch =&amp;gt; {
    return {
        getDataCDragon: tftData =&amp;gt; dispatch(getDataCDragon(tftData))
    };
};

export default connect(null, mapDispatchToProps)(InitData);
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Inside action &lt;code&gt;GetData.js&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;An action can easily be put inside the component where it's used. However, it is best practice to separate the actions from the components. The code will be cleaner and easier to understand.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// GetData.js
export const getDataCDragon = tftData =&amp;gt; {
    return (dispatch, getState) =&amp;gt; {
        // make an async call to database
        dispatch({ type: 'GET_DATA_CDRAGON', tftData });
    };
};
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Inside reducer &lt;code&gt;MixedReducer.js&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;I named it MixedReducer because it used to be my &lt;code&gt;rootReducer&lt;/code&gt; until I added more reducers so its name had to adapt.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;...state,&lt;/code&gt; is very important because we don't want to overwrite the &lt;code&gt;state&lt;/code&gt; (all the data) inside the store&lt;/li&gt;
&lt;li&gt;Just keep names consistent, don't bother confusing yourself with different names in different files.
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;// MixedReducer.js
// **********************************************
// **** Using Redux Checklist ****
// **********************************************
/*
    1.) connect component to store
    2.) map state to props (get data) or map dispatch to props (set data)
    3.) in the component, use maapped data with this.props
    4.) add the mapped const into the connect HOC - order goes connect(mapStateToProps, mapDispatchToProps) null if empty
    5.) the mapped const calls an action (separation of concerns) -&amp;gt; make action, e.g. UPDATE_DATA
    6.) reducer will catch this action -&amp;gt; create switch case for that corresponding action 
*/

const initState = {
    itemsData: [],
};

const mixedReducer = (state = initState, action) =&amp;gt; {
    switch (action.type) {
        case 'GET_DATA_CDRAGON':
            return {
                ...state,
                itemsData: action.tftData.itemsData,
            };
        default:
            return state;
    }
};

export default mixedReducer;

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;b&gt;Why do all of this? Why even use Redux? What's the point of saving the data to the store?&lt;/b&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Since &lt;code&gt;&amp;lt;InitData /&amp;gt;&lt;/code&gt; was called at App.js, we can use the parsed data by passing it through props to its children. The first iteration of the app worked like that, but it was too tedious passing data around with props. If you suddenly need to add new data on a child component you have to props pass that data all the way from parent to child, parent to child, parent to child.&lt;/li&gt;
&lt;li&gt;The best practice for connecting a component to the store is to use the connect HOC (higher order component), i.e. &lt;code&gt;export default connect(null, mapDispatchToProps)(InitData);&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;The component being connected to the store means it can watch (or read) any data from the store via &lt;code&gt;mapStateToProps&lt;/code&gt; which would have been where &lt;code&gt;null&lt;/code&gt; was in our code --&amp;gt; &lt;code&gt;export default connect(null, mapDispatchToProps)(InitData);&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;Read from store --&amp;gt; &lt;code&gt;mapStateToProps&lt;/code&gt;. &lt;/li&gt;
&lt;li&gt;Write to store --&amp;gt; &lt;code&gt;mapDispatchToProps&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;In conclusion, we are using Redux to write our data to the store. Allowing us to easily read it later on inside other components.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;**Update**&lt;/h1&gt;

&lt;p&gt;I didn't use select at all. Current progress shown in Gif below. Back-end completed. Because it is working, I can now continue the documentation of current build. &lt;br&gt;
&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc4x7ai45nsi4zsu8niip.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fc4x7ai45nsi4zsu8niip.gif" alt="update- backend works"&gt;&lt;/a&gt;&lt;/p&gt;

</description>
      <category>tft</category>
      <category>api</category>
      <category>axios</category>
      <category>redux</category>
    </item>
    <item>
      <title>How to make a user friendly select when using React, Redux, and Firebase (Part 1) - Goal</title>
      <dc:creator>Lestley Gabo</dc:creator>
      <pubDate>Thu, 30 Jan 2020 01:47:00 +0000</pubDate>
      <link>https://forem.com/lestgabo/how-to-make-an-updateable-select-with-react-redux-and-firebase-part-1-lph</link>
      <guid>https://forem.com/lestgabo/how-to-make-an-updateable-select-with-react-redux-and-firebase-part-1-lph</guid>
      <description>&lt;p&gt;This is just documentation so far. So there's no hand holding. I have a goal in mind on how the finished feature will be.&lt;/p&gt;

&lt;p&gt;I am working on an app &lt;a href="https://www.tft-helper.com/" rel="noopener noreferrer"&gt;https://www.tft-helper.com/&lt;/a&gt;. It helps users play TFT (Teamfight Tactics). I have received a lot requests for the champions to have item recommendations. TFT updates very quickly and even had a whole new set of champions and items recently. I used to have item recommendations in Set 1, but I removed it in Set 2 because it was too much of a hassle to manually update.&lt;/p&gt;

&lt;p&gt;Item recommendations need to be up to date. Instead of me updating the database manually for it. I am going to add a new feature. This feature will allow me and users (if they pay me, because I'll give them admin access) to easily update the item recommendations to our liking.&lt;/p&gt;

&lt;p&gt;Breakdown of my goal:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;this is a tooltip for a champion
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fz688f2jrlrpdtfp2i0aq.png" alt="Alt Text"&gt;
&lt;/li&gt;
&lt;li&gt;I want 3x item slots at the bottom
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4hfzwwgpekyvv6en28up.png" alt="Alt Text"&gt;
&lt;/li&gt;
&lt;li&gt;that when clicked opens an item table to select from
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F018v7d777ry5vo0ghh36.png" alt="Alt Text"&gt;
&lt;/li&gt;
&lt;li&gt;the item slot is then updated to the selected item
&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgrp1222kyuuh7puqcaj6.png" alt="Alt Text"&gt;
&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>react</category>
      <category>redux</category>
      <category>firebase</category>
      <category>select</category>
    </item>
  </channel>
</rss>
