Various lesser known features in React


Forms, uncontrolled components, Server Side Render (SSR) and various tips, tricks in React

Innovative Solutions and Technologies Center(ISTC)

Yerevan, Armenia

By Edgar Aroutiounian, Summer 2017

Progress:

Outline of this lecture


React has many tips and tricks, this lecture will touch on quite a few of these lesser known and used capabilities.

Forms forms forms


Form input is one of the most basic things that any web application can and should do. Think of all the times you have to input password, usernames, first names, last names, etc etc. All of these are web forms and the issue they raise is who should hold the state? Think of the text that is typed in an input, it naturally has some state, it is keeping what the user wrote.

With React we have a choice as so who should manage that state, the React code (us) or the browser. The difference between this is the difference between controlled and uncontrolled components.

Controlled Components


If we control the form, then we call it a controlled Component

import React, { Component } from 'react';
class UserInput extends Component {
  state = { username: '' };
  user_changed = e => this.setState({username: e.target.value});
  render() {
    return (
      <div>
        <p>User is: {this.state.username}</p>
        <input type={'text}
               value={this.state.username}
               onChange={this.user_changed}/>
      </div>
    );
  }
}

Notice that using controlled components forces us to use a class as we need to have this.state. It is called controlled because we are controlling the value of the input, not the browser.

Uncontrolled Components


class UserInputExample extends React.Component {
  show_input_value = () => {
    const { value } = this.real_input;
    alert(`Real value was: ${value}`)
  }
  render() {
    return (
      <div>
        <input type={'text'} ref={ref => this.real_input = ref}/>
        <input type={'button'}
               value={'Click me to do alert'}
               onClick={this.show_input_value}/>
      </div>
    );
  }
}

Every HTML component gives you a chance to let you have the real HTML element. Remember that React is a view library abstraction, it sits on top of the real DOM elements. However, sometimes we do have to have the real HTML element. React gives us that chance with the ref prop, which needs to be a callback. Your callback will receive the actual HTML element.

Why use uncontrolled Components?


You really shouldn't use refs, they break the model of React but one area where they are useful, as you can see, is with Forms (all the different types of input HTML elements elements).

Imagine a healthcare form with 10 different input, for each of those form inputs, you'd have to write the value in this.state, write that for the value, aka value={this.state.something} and of course the onChange handler, which needs to be a function. This is a lot of coding clutter and boilerplate. Hence using uncontrolled components is sometimes a cleaner solution but when you are first starting out, you should probably use the React way, aka controlled Components.

https://facebook.github.io/react/docs/forms.html

Children of Components


React also lets the parent Components somewhat know about their children. We have a handle to that in props, this.props.children

class Container extends Component {
  render () {
    return (
      <div>{this.props.children}</div>
    );
  }
};

const App = () => (
  <Container>
    <p> first</p>
    <p> Second</p>
  </Container>
);

This is useful when the parent component doesn't know what its children components will be, you will see this in libraries like react-router.

https://facebook.github.io/react/docs/react-api.html#react.children

Default props


Sometimes we know ahead of time what props our Components should use, in those cases we can assign default props

class Container extends Component {
  render () {
    const { name, age} = this.props;
    return <p> I am {name}, and am {age} years old</p>;
  }
};

Container.defaultProps = {
  name: 'Spitak',
  age: 23
};

But of course if you explicitly give different props when making the Component in JSX, then those will be used instead.

Server Side Rendering


One of the best features of React is that the core of the library does not assume the existence of the DOM. This means that we can use React on the server side.

The benefit of it is multifold but the top reasons are that we actually have a site to show search engines when they crawl our site so SEO improves and we lessen the work for the client since we have initial HTML to show rather than force the client to run a lot of JavaScript code before having the user see anything at all.

This is easiest done with a node backend

Server Side Rendering Example


import { renderToString } from 'react-dom/server';
import Application from '../lib/silicondzor';
// Somewhere in our request handler
...
    const html = renderToString(<Application/>);
          res.end(`
<!doctype html>
...some standard link, meta tags
<div id={'root}>${html}</div>
`);
https://github.com/fxfactorial/silicondzor/blob/refactor/backend/server.jsx#L83

https://facebook.github.io/react/docs/react-dom-server.html

Cloning children with new Props


Sometimes we want to have a React element but with different props, this usually comes up in the context of this.props.children

class Parent extends React.Component {
  use_this_handler = (e) => {// Some code};
  render() {
    const with_props =
       React.Children.map(this.props.children,
         child => React.cloneElement(child, {click_handler: this.use_this_handler})
    );
    return <div>{with_props}</div>;
  }
};

Here we are going over each of the children that this component would usually have, but we're replacing the click_handler prop with a different handler. You can see that the second argument to cloneElement is the new props and they will be merged with the existing props of that element.

https://facebook.github.io/react/docs/react-api.html#cloneelement

Example usage of cloneElement


Here we want to change just the size while keeping the color the same

import React, { Component } from 'react';
import Star from 'react-icons/lib/fa/star';
import styled from 'styled-components';

const Wrapper = styled.div`
 display:flex;
 flex:1;
 height: 500px;
 flex-direction: column;
 background-color: hsla(5, 10%, 10%, 1);
 align-items: center;
 justify-contents: center;
`;

class MyStar extends Component {
    render() {
        return <Star
        style={{color:this.props.color}}
        size={this.props.size}/>;
    }
}

class App extends Component {
    render() {
        const elem = (
            <MyStar
               size={150}
               color={'hsla(100, 50%, 50%, 1)'}/>
        );
        const copied =
                  React.cloneElement(elem, {size: 400});
    return (
      <Wrapper>
        {elem}
        {copied}
      </Wrapper>
    );
  }
}

export default App;

This examples uses styled-components and react-icons, but neither are strictly necessary.

$ yarn add styled-components react-icons