Day… 8? Catch ups! Also, doing some select input & validation in Redux Form!

Some Personal Update

Wow, been a while since I last blog. Couple of things happened:

  1. I decided to dive fully into the Udemy React course pack I got (Modern React with Redux).
  2. A friend gave me a book on algorithm to study for future interview, which I sadly could not understand. I ended up purchasing an algorithm book that I got from the library previously – I only read it half way before it was due, but I did understood it. Once finish that, I am going to give my friend’s book another crack.
  3. I found a few internship to apply, with one requiring that I start on opensource contribution, which require me to set up an opensource project’s environment in the first. For those who have a bit more experience in development, I think we all know that can go……
  4. My family decided to travel for 3 whole weeks in Japan & Hong Kong, where the last 2 week consisted of living in a tiny bedroom with no table. My neck did not appreciated the experience. While I love – love – Japan, 3 weeks of 24 hours living in extremely close quarter with anyone is a bit too much. I have never been so happy to be back in San Francisco. If I ever tell you I am going to travel with my family to Asia for over 2 week in the future, STOP ME!

*cough* Yea, it’s been a bit eventful. The fact that I got sick the week I got back doesn’t help.

Anyway, I finally got some progress. I started with the Form component. The key issues I worked on are validation and incorporating <select> tag in Redux Form. I started coding with the example code in Redux Form’s  Field-Level Validation page.

Problem A: Select Input Tag

In the example, each input element is a <Field /> component, which contains an attribute named “component”. The component attribute accepts a method, which is named renderField() in this case. Props are passed to the called method – again, renderField in this case. The renderField() method contains code that outputs <input> tag using the data in the props passed by <Field />.

The problem for me is that I wanted to output one single <select> input element, while renderField()‘s code only output <input> HTML. For those who are not familiar with HTML, select is one of the very few input element that does not use <input> as its HTML – it uses <select> and the child element <option>.

While I can hard code the <select> <option> HTML, is there a way I can use the component feature to dynamically generate out the input fields?

So there are various solutions I can tried:

1) Check Redux Form’s <input> type

Natively, <input>’s type attribute does not recognize select as possible values. But hey, you never know – maybe Redux Form’s Field component do. It’s not in the documentation either, but let’s give it a try!

Result: Nope.

2) Change <Field /> into <Field></Field>

Maybe if I put in an <option> type somewhere? But Field component in the example is self-enclosing…… Let’s try to change it into <Field></Field> and put <option> between!

Result: Nah…

3) Conditional statement in renderField()

I guess I can use conditional statement to check if the input type is select…

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
const renderField = ({ input, label, type, children, meta: { touched, error } }) => (

<div>
    <label>{label}</label>
    <div>
      {
        (type === "select")
        ? <select {...input}><option>Test</option></select>
        : <input {...input} placeholder={label} type={type} />
      }
      { touched && error ? <span> {error} </span> : '' }
    </div>
  </div>

)

Result: Of course it works, but the conditional statement will be check each time <Field> is rendered. I don’t want to add unnecessary complexity. My app is small, so it only have 2 input element, but I want to build it to have good maintainability if the code get bigger.

4) Add a new method, such as renderSelect()

I could put the select HTML all into a new method, used as a value for <Field />’s component attribute only when <select> is needed.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
const renderField = ({ input, label, type, meta: { touched, error } }) => (

<div>
    <label>{label}</label>
    <div>
      { <input {...input} placeholder={label} type={type} /> }
      { touched && error ? <span> {error} </span> : '' }
    </div>
  </div>

)
const renderSelect = ({ input, label, type, meta: { touched, error } }) => (

<div>
    <label>{label}</label>
    <div>
      { <select {...input}><option>Test</option></select>
      }
      { touched && error ? <span> {error} </span> : '' }
    </div>
  </div>

)

Result: That’s better! But…

Problem B: Option tag!

As I mentioned earlier, <option> is a child element for the <select> tag. For those unfamiliar with HTML, option is used to output the choices in an select input element. In my case, my options are: Muni, Bart, and Caltrain.

Also mentioned earlier was that <Field /> is a self-enclosing tag in the examples. My question lies in how I should insert something like option, which is a child element and is different for each select input element?

Let’s try some possible solution:

1) Hard Code:

In this case, I only have one select input type, so I can hard code the options of muni, bart, and caltrain.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const renderSelect = ({ input, label, children, meta: { touched, error } }) => (

<div>
    <label>{label}</label>
    <div>
      {
        <select {...input}>
          <option value="">--None--</option>
          <option value="muni">Muni</option>
          <option value="bart">Bart</option>
          <option value="caltrain">Caltrain</option>
        </select>
      }
      { touched && error ? <span> {error} </span> : '' }
    </div>
  </div>

)

Result: … Yea, it works, but only for one select element. What am I going to do if I add more select input element in the future???

2) Change <Field/> to <Field></Field> & insert <option> between them

It didn’t work earlier during Problem B because I had hope that if I do <input type=”select”> in renderForm(), putting in <option> between <Field></Field> would somehow work due to Redux Form magic. Such magic did not exist.

But, now I have a renderSelect(), which outputs <select> HTML, will putting <option> between opening and closing Field tags work?

Result: Nope. In hindsight, if renderSelectInput() outputs <select> HTML, how would it even know to insert all the <option> tags before the closing tag of </select>?

3) Check if the props passed by <Field /> include child element data

Wait, do the props passed from <Field /> to renderField()/renderSelectForm contain data from child element?

1
2
3
4
5
6
7
8
9
10
11
const renderSelect = ({ input, label, children, meta: { touched, error } }) => (

<div>
    <label>{label}</label>
    <div>
      {  <select {...input}>{children}</select> }
      { touched && error ? <span> {error} </span> : '' }
    </div>
  </div>

)

Result: Ok, that works! Yes!

Problem C: Validation

Field component contain an attribute called validation. If the method or value called returns anything other than undefined, it knows an error have occurred and passed the returned String to the method called by components as the prop meta.error.

If you take a quick look at the example’s top section, the validation is not exactly fun to read. It is also hard coded and not flexible. So, let’s create a method for validation that generates error code more dynamically:

1
2
3
4
5
6
7
8
9
const validate = values => {
  const errors = {};

const options = ["muni", "bart", "caltrain"];
  errors.agency = (!values.agency || options.indexOf(values.agency) === -1 ) ? "Please select a valid agency" : '';
  errors.stopCode = ( isNaN(Number(values.stopCode)) || values.stopCode.length &lt; 3 || values.stopCode.length > 7 ) ? "Please enter a valid stop code" : '';

return errors;
}

And by adding valid as an argument for reduxForm(), the call to validate() would be automatic due to <a href=”https://redux-form.com/7.2.0/docs/api/reduxform.md/#-code-validate-values-object-props-object-gt-errors-object-code-optional->ReduxForm API. I don’t have to hard code in valid=valid() every single time!

1
2
3
4
5
6
7
8
9
const validate = values => {
  const errors = {};

const options = ["muni", "bart", "caltrain"];
  errors.agency = (!values.agency || options.indexOf(values.agency) === -1 ) ? "Please select a valid agency" : '';
  errors.stopCode = ( isNaN(Number(values.stopCode)) || values.stopCode.length &lt; 3 || values.stopCode.length > 7 ) ? "Please enter a valid stop code" : '';

return errors;
}

That’s a lot less chaotic, isn’t it? My next step should be the output data once form fetch the JSON, but let’s rest for now. Until next time!

Day 7: Async Testing

So, definitely haven’t been working on the app lately. It’s been another busy week – went to the Livability Award, added new features to the Sponsorlane dashboard, and attended the API World Hackthon. I ended up not the participating in the hackathon, but I got to check out some cool companies and played around with Citi’s new beta API.

React app wise, I only got to work on the async action testing, using Redux’s doc as guide. I also commented out a bunch of unfinished code so they wouldn’t interrupt when I start the test commands. As a result, the testing is working again, and I find some error in components file. The testing is also giving a false positive for the async actions, but that should change once I get the stores in and commented out a few things.

Day Six: Slower progress this week. Worked on container & prop-types.

For the last weekend, I spent the days emerge in WordCamp Sacramento 2017. It was my first WordCamp, and it was awesome!

Since I didn’t carry my macbook all the way over to Sac, I spend most of my off time studying JavaScript in my iPad. Namely Learning JavaScript Design Patterns by Addy Osmani and Modern React with Redux by Stephen Grider.

So, for me, it was more about building fundamental this weekend. Progress-wise in my app:

  • Refactored the input form from version 1 in my Nextbus Connect project to my component, Form.
  • Incorporated prop-types.
  • Worked on container with React doc as reference, adding in mapStateToProps() and connect() for the reducer.

 

Day Three: Looking at Redux Doc

So, create-react-app got started, testing environment is set up, directory is organized. Time to write more code than just test placeholder files.

It’s been over a month. so my memory of Redux is a bit blurry – but it’s ok, redux.js.org to the rescue! Reading their Todo List example and some of my old codes jogged my memory.

Here is the latest directory structure, with all the new files in. At the right is the current state of action creator, action.js.

action creater
Action Creater file, action.js

There is also a basic combineReducer in reducers/index.js. So far, the test file just check that the files in the components are outputting div. For now, I am mostly just setting up some empty functions.

Day 2: React File Organization and Understanding Syntax for Chai with Enzyme

Second day of my every-other-day-React-project-progress-posting (I need a better name… suggestions, anyone?), with the Day One posting here for those curious: Day One: Create-React-App with Mocha and Enzyme – with No NPM Eject!

Task One: File Organization

So, I was creating the directory organization for NextBus Compare. Looking at my previous sketches of possible file structure for my project:

file structure sketch
An old sketch from about a month ago

plus being so new to Redux, I am going to stick with the tradition method of organizing it by function/nature. For those who want to read about React file organization, there are 2 articles that I found useful:

They each called the typical organization method different name – function or nature centric. François also advocated for what he called a domain-centric approach, while Mikey went with a feature-centric approach. I have personally done domain-centric before, and did like it quite a bit. For this one though, I am going to play it safe because my focus is to learn Redux here.

So here is my current file structure:

Nextbus Compare File Structure
Nextbus Compare File Structure

Task Two: Writing Test Files

Once there are new files, I tried to write test files to make sure all the files are loading, even though they only load empty div at this point.

Then I slowly realize that every googled posting for Mocha/Chai/Enzyme seemed to have different but very similar syntax. Therefore, I have a lot of tabs open but is very confused.

*Sighs*

Eventually, I just close every tab, and search for the documentation for Chai and Enzyme. Restricting my reference source made it easier. Here is one of my test file:

Nextbus Compare Test File
The App.spec.js test file in my Nextbus Compare app

Save

Day One: Create-React-App with Mocha and Enzyme – with No NPM Eject!

There is a saying. Job hunting is a full time job. God, were they correct. I have been splitting my time between reading postings, researching companies, applying jobs, updating job site portfolios, interview prep, code testing (recently did a React app in 5 days), networking in-person and online, helping out at startup Sponsorlane, and still staying updated with tech news.

By the time Labor Day rolled by, I realized I haven’t worked on my side project involving Redux and mocha for over a month! Not to say I haven’t learn anything – I have been studying algorithm and design pattern. My debug and Node skill have also noticeably improved thanks to my effort in Sponsorlane. But I set up the goal to learn Redux and mocha months ago, and I want to finish what I started, damn it!

Thus, I am setting a new goal. I am going to re-start my app, Nextbus Compare. A fresh start. This time I will record my process: I will update my app one day, and post the process the next day.

So, here is Day One! The topic is:

Create-React-App with Mocha and Enzyme – with No NPM Eject!

The last time I tried to do this, there were multiple different sources of guides, most of them either confused me with too many steps or didn’t worked. I ended up doing npm eject. I also wasn’t what I did and what package I installed to made it work. This time, I am much more prepared. So, here is what I did:

I started with Dave Schinkel’s blog post, Mocha + Enzyme with create-react-app. It is a good read, although there are some things that don’t work with my system. Here is essentially what I did.

  1. create-react-app nextbus-compare
  2. Since I don’t have yarn installed and babel-preset-react-app kept giving me import errors, I did npm install –save-dev es2015 babel-preset-react preset-stage-0. While Dave stated es2015 is ignored by create-react-app, I ended up needing it. The use of babel-core compiler later on resulted in import error because babel-core don’t recognize jsx. As a babel newbie, I don’t know why my outcome was different. I just know that babel-preset-react-app doesn’t work on my system. Please comment if you know why……
  3. In package.json:
    1. Added: “babel”: { “presets”: [ “react”, “es2015”, “stage-0” ] }
    2. Modify “test” command to: “NODE_ENV=development mocha –compilers js:babel-core/register –require ignore-styles src/test/*.spec.js” . Note that in Dave’s post, his test command is missing the double quotes. Not a big deal, but if you were a Node newbie like me, know that double quote is required! Also, there is an additional –require ignore-styles here. That’s because if I don’t, babel-core will try to compile css files as js files, therefore triggering “unknown token” errors:
      CSS unexpected token
      The unexpected token

      There are ways to bypass it, but I don’t plan to test my styles at this stage, so I am just going to do a simple –require ignore-styles in my test command line.

  4. For testing, depending on if you also want chai or sinon, you would do npm install –save-dev mocha enzyme chai sinon react-test-renderer. Note that react-test-renderer is a a dependency requirement for enzyme. Without it, you will get this error message:

    Enzyme implicit dependencies
    Implicit dependencies error!
  5. Here is a very simple test script I did in src/test/App.spec.js:

    test file
    Super simple test file
  6. Now do a simple npm test, and this should happen:
Mocha testing successful
Test Successful!!!

That’s it for day one!

Save

Save

Doing React in 14 Hours: Hacking For Humanity 2017

“Damn, those kids are smarter than me!” I whispered to Jessica, who laughed and playfully slapped me in the arm. We watched in awe as the kids – middle schooler going to high school – talked about wanting to build their app in Java and the algorithm involved (“I didn’t know computer existed when I was in middle school!” “…We sound so old!”). The joy of hackathon – you see all sort of ideas and participants.

The Event

I was at DocuSign HQ for Hacking for Humanity, hosted by Girls in Tech and Hackbright and sponsored by DocuSign, Cisco, Kintone, Handshake, Memebox, and JINS. Topics we can select may include Homelessness, Sexual Assault, Domestic Violence, Human Trafficking, or Women’s Health.

The host decided to assign us into teams in advance. Like all events though, we have a bunch of MIA attendee – Missing In Action. So, those us missing members waited in line for reassignment. While there, I started chatting – which led me to me be invited into another team before the re-assignment.

We started as 4 person team – UI/UX designer Jessica and Tawny, software engineer Anoja, and myself as web developer. The host wanted a 5 person, so they assigned us Ryu, engineer and Kintone evangelist visiting from Japan.

Opening talk took the whole morning – Hackbright even did a Coding 101! For me, the most interesting part was listening to SF Safe House and Women Inc’s work and mission.

DocuSign CEO Opening
SF Safe House
W.O.M.A.N., Inc
Special gifts from sponsor Memebox

Since this hackathon didn’t have idea pitching, our team are formed without a project idea or even a common topic interest. My team eventually decided to go with Women’s Health: HerCare, a web app that extracts SFGov Opendata and list nearby free health care clinic, then help user to easily find transportation route.

UI working… on the DocuSign window, with the Bay Bridge as background pic.

Onto Hacking

Both Anojo and Ryu mentioned they know a bit of JavaScript, so I decided to go with React. As with all projects, I quickly encounter issues.

Styling in React

Being in a time-constrained event like hackathon, I decided to use Bootstrap. But altering DOM other than React is considered bad practice: Bootstrap contain its own JavaScript, which conflicts with React. The common suggestion online was to use react-bootstrap.

fetch() and Component Lifecycle

For some reason, console.log revealed that the state is not setting with the data I retrieved in fetch() when I use the OpenData API. Looking into React’s fetch(), I learned that it returns a promise that must be waited. Meanwhile, render() is also setting state and mounting. To ensure the state are set in the mounted component befire re-rendering is trigger, API calls with setState() should be done in componentDidMount().

Latitude & Longitude via Google Map API

While trying to get Google Map working, I spent too much time on the wrong npm packages. I had picked one of the recently updated one with a simple example, thinking it would be a snap.

Wrong.

Fortunately, when I finally switch to a different one someone recommended in Reddit (react-gmaps), it worked almost right away. After that, I needed to get the latitude and longitude by address – regular user obviously wouldn’t be entering their latitude and longitude.

Having been working with bunch of npm packages lately, I jumped onto the npm-package-solution again. Silly, since it turns out Google have an API for that.

*Sigh* The precious hours… Almost submission time!

Controlling State Updates via componentWillReceiveProps() & componentDidUpdate()

When users clicked on the parent component, LocationList(), which holds the address, it should updates the child component, GoogleMap(). The update involves calling the Google API that detects latitude and longitude.

So, another API call. I would use componentDidMount(), right? I mean, the React doc say so itself:

If you need to load data from a remote endpoint, this is a good place to instantiate the network request.

…yea, didn’t worked. The question is why?

Well, the thing is that the map component (GoogleMap in this case) was first mounted, then its states changes when the parent component (LocationList) holding it passed down a new prop that activates an update – not a new mounting. What I need was componentDidUpdate().

But when I did the API call in GoogleMap and use setState to update the states with latitude and longitude data, the component itself will update, again.

This is an infinite loop.

That’s where componentWillReceiveProps() came into use. I set up a flag variable, “updated”. In the constructor, it is initialize as false.  Inside componentDidUpdate(), an if statement checks the flag. If false, we do the API call, setState, and set “updated” to true. After that, the subconsquent update from state change will not activate another API call because the flag variable is now true. Only if the component receive new props from the parent component LocationList(), – in another word, someone click one of the address listing – would the variable “updated” be set to false and thus activate the API call.

Deployment on Heroku

Unfortunately, I didn’t solve the infinite issue until after the submission. Fortunately, I have continuously deploy my site onto Heroku. Deploying React onto Heroku is acutally a snap. The Heroku team have a instruction page just for that: Deploying React with Zero Configuration. I do have do a npm run build to get it running, but after that, it’s smooth sailing.

Team Communication

Due to language barrier and differences in programming specialty, we ended up doing the same task by accident at first, so stop coding and checking in became essential. Though the programmers in my team knows JavaScript, latest JavaScript and web development best practices isn’t exactly their specialty. In the end, Ryu ended up finding jQuery to be easier to do. In hindsight, I should have realize that language barrier may prevent my teammate from using React, which had an all-English doc. Fortunately, Ryu was good with at AWS, which he easily use to deploy his jQuery.

Ending

Prototype: HerCare Location Listing
Prototype: HerCare Appointment Request
The demo! HerCare main page
Demo: HerCare Location List

The challenge of this competition was definitely communication and task distribution. It was a bumpy ride, but we eventually find our rhythm. Both Anojo and Jessica was inspired to do more hackathon, so I recommended July’s AngelHack in Silicon Valley to them – we will probably bump into each again as a result!

HerCare Team!

Lego, Fistfight, GraphQL, & Observable – React in Silicon Valley

Real World React had its first Silicon Valley meetup. As a React newbie who enjoys the Silicon Valley cities, naturally I attended!

Held at Atlassian, this is the Meetup “GraphQL with REST APIs | RxJS & Redux-Observable“.

Real World React at Atlassian

We started off with the Lightning Talks, and the first one up is Joshua Nelson from Atlassian. His original topic line is “Component libraries and React as a platform”. The final version of his topic? “Why Lego is Great”!

I concur! Lego is Great!!!
More Legos!

Lego have a rich history and culture, which Joshua started his talk with and eventually turned it around to Atlassan’s component library, discussing its 3 key advantages: Clean API, Reusable, and Platform.

Then Michael Leung and David Katz talked about their Reactathon project. Utilizing the OpenTable API, their project BrokenTable determines which bar is most likely to have bar fight.

Yep, bar fights.

All while the developers are students too young to even step into a bar.

Those orange dots are fist!
That black thing is actually a broken table. A non-broken table means no fights

Needless to say, the idea was hilarious, and the duo succeeded in giving a presentation that was both funny and educational. I particularly enjoyed their presentation of how their code works and how they implemented React Native and Redux in the fast-paced environment of a hackathon.

After a brief break, Feature Talks started, with the first one being on of my main goal for attending this Meetup: “Going GraphQL First on Web and Mobile” by Jon Wong from Coursera. I am considering GraphQL for the next on my to-learn list, so this is perfect timing!

Jon discussed about the task to implement GraphQL in an existing project – a task he found similar to what Justin Bachorik mentioned in the Reactathon talk regarding NPR’s transition from legacy code to React. Both are accomplished through the process known as incremental adoption.

Speaking of, I have been studying Redux, and I don’t envy the future me that will eventually adopt Redux for my React project. Incremental adoption indeed.

Jon touched on how Joshua talked  API contract earlier in the Lightening Talk and stated that GraphQL inverts API contract back to client, who is the the one to actually build product. Such schema-first approach helps create better contract.

For someone planning to learn GraphQl, his description is helpful in giving me an idea of what and why I should learn it. His diagrams also did a great job in graphically representing how GraphQL works with React’s Component-focused system.

GraphQL & Server.
GraphQL and React working together in Coursera. The visuals and the way he presents really showed why they interact well with each other!

The last but not least (oh, definitely not least) is Berkeley Martinez, CTO at freeCodeCamp. Perhapes a reflection of his work, he is quite excellent in teaching – seriously, I have zero clue of what Observables when I started. Yet, I wasn’t lost with the amount of codes he displayed, and I came out with a pretty good understanding. He was very good at being precise yet informative and to the point.

I love the definition here.
Once again, concise but to the point.

I must say, this Meetup was one of my most satisfying I had. Meetup that shows lots of codes and teaching materials can be dull if it is not a tutorial everyone can follow. Not a lot can be fun, inspirational, and technically informative. This definitely hits all the spots. I can’t wait to attend another one!