Monthly Archives: August 2019

Renaming a git branch

Occasionally you need to rename a branch you’re working on in git. The following shows how to rename the branch and push commits (assuming the branch had already been pushed) to a remote location

Note: if the branch has not been pushed to a remote location you only need to use the first two commands

  • git checkout <old_branch_name>
  • git branch -m <new_branch_name>
  • git push origin –delete <old_branch_name>
  • git push origin -u <new_branch_name>

Storybook and state (also uses @sambego/storybook-state)

There’s several ways to setup your components for testing within Storybook to allow us to change our component’s properties – using Knobs or creating wrapper components to encompass state changes through to hooking up to a redux store.

Let’s look at an example of wrapping our component within a story.

So I have an AppBar within a selection component. I want to see the story maintain the state changes when the user changes the selection. Now, no actual state is stored within the component itself as it’s passed up the component hierarchy to a parent component and/or redux store. This means, without setting up a parent component or redux store the selection changes but the actual value on the component remains the same.

One way to achieve this is to create a wrapper parent component, i.e. a minimal wrapper component around our component under test, for example

class WrapperComponent extends React.Component<any, any> {
  constructor(props) {
    super(props);

    this.state = { ...props }
  }

  render() {
    const props = { 
      ...this.props,
      onSelectionChanged: (selected, _) => this.setState({selected: selected}),
      selected: this.state.selected
    }

    return <ComponentUnderTest {...props} />
  }
}

So as you can see, the ComponentUnderTest is wrapped in a WrapperComponent and hooked up to props along with state changes, now we simply have the story return the WrapperComponent, i.e.

const props = {
  selected: 'None'
}

return <WrapperComponent {...props}/>

Easy enough and could be rewritten to make it more generic, but there’s an alternative and that’s to use something like @sambego/storybook-state

yarn add -D @sambego/storybook-state

In which case we can write our story like this instead

import { Store, State } from "@sambego/storybook-state";

const storeState = new Store({
  selectedPublicQuery: "None"
});

storiesOf("ComponentUnderTest", module)
  .add("default", () => {
    return (
      <State store={storeState}>
        {state => 
          <ComponentUnderTest selected={state.selected} 
              onSelectionChanged={(selected, _) => storeState.set({selected: selected})}/>
          }
        </State>
      );
  });

Storing extra data within your HTML elements using data-* attributes

I came across a simple problem, I have an array of objects in React with a name (something to display to the user) and an expression tree (which makes up a query associated with the name).

What I wanted to do is that when a name is selected in a material-ui Select component, that it then passes the name and the expression data to a handler.

Ofcourse there are several ways to achieve this but this is a really simply solution. We create an array of MenuItem‘s for the Select and we store the expression tree along with the MenuItem

If you take a look at Using data attributes you’ll see that HTML5 has a way of adding attributes to an element using the data-* syntax.

The name of the attribute to be added simply starts with data-, for example data-expression and now when the Select onChange event is handled, we can get at, not only the value selected but also the data attribute value.

Here’s an example of us setting up a MenuItem

return [{name: "None", expression: undefined}]
  .concat(publicQueries).map(e => {
    return <MenuItem key={e.name} 
      value={e.name} 
      data-expression={e.expression}>{e.name}</MenuItem>
});

Notice that we simply declare the data-expression and assign some data to it. Nothing special here.

Now within the onChange handler of the Select component we might have a handler like this

handleOnChange(e: any, child?: any) {
   const selecteNamed = e.target.value;
   const selectedExpression = child.props['data-expression'];
   // do something useful with these
}

Debugging redux

Whilst developing our UI and using redux to store our model things can get complicated when trying to understand what’s going on – did the reducer get called, what’s the state of the data in redux etc.

I’m using storybook primarily for my own testing, whilst the information below is not specific to storybook, it is a useful way to keep this stuff out of the production code.

First we need to add Chrome (or Firefox) extensions/add-ons to enable us to use the redux viewer (see https://github.com/zalmoxisus/redux-devtools-extension). When installed a Redux option should appear in the Chrome (or Firefox) debug tools and selecting it will display the redux extension which give us a way to see each dispatch message, the changes in the redux store and dig into what’s currently stored in redux.

Let’s start tings off by installing the following

yarn add redux-devtools-extension -D

Now we need to plug the dev tools into the redux store, so I’m creating a store in my story and the code looks something like this (where myReducer is obviously the reducer I’m using, initialState is obviously the state I wish to prime the redux store with, i.e. my test data). In the example below I’m using the middleware, the redux-promise-middleware this is all passed into the composeDevTools which is basically the link to the previously installed Chrome (or Firefox) dev tools.

import { composeWithDevTools } from 'redux-devtools-extension';

const store = createStore(myReducer, initialState, 
  composeWithDevTools(applyMiddleware(promiseMiddleware)));

That’s all there is to it, now run your code up, display the dev tools in Chrome (or Firefox) and select the Redux option then interact with your UI to see redux dispatched message etc.

Promises within your Redux code

You’ve created your Redux reducer code and you want to get data from a remote location using fetch or axios etc. or for that matter any functionality that runs asynchronously and returns a Promise.

Let’s look at an example of some code contrived code which hopefully makes things a little clearer

export const queryDataSource = (query: string) => {
  return {
    type: ActionType.Query,
    payload: new Promise<any>((resolve, reject) => {
      // simulate a async query
      setTimeout(() => {
        resolve();
      }, 3000);
    });
  };
}

In this example code, I wanted to make it really obvious what was going on under the hood, hence we return a Promise as the payload and the promise could encapsulate a server call, but in this case we”ll simulate this with a simple timeout.

We’d now normally handle this in a switch statement like this

  switch(action.type) {
    case ActionType.Query:
      return {
        ...state,
        data: action.payload
      };

However this isn’t what we really want to happen as the payload is a Promise. What we want is to handle the change in Promise state in an asynchronous way.

Most likely we’ll want a flag in our redux data which is bound to a property that alerts the user when an asynchronous operation starts (i.e. shows a progress indicator), then alerts the user to the operation completing and also displays errors in the operation fails and ofcourse stores the results of the operation into the redux store.

This is all fairly simple to do in code using a Promise and with redux-promise-middleware it’s equally simple to do with redux. This middleware converts the Promise into three separate events which can be handled within the redux switch function.

To add redux-promise-middleware, we do the following

  • Run yarn add redux-promise-middleware
  • Next we need to add the promise middle ware to our store creation, for example using applyMiddleware(promiseMiddleware) such as the example below
    import promiseMiddleware from 'redux-promise-middleware';
    
    const store = applyMiddleware(promiseMiddleware)(createStore)(
      combineReducers({
        queryReducer,
        connectionReducer
      })
    );
    

The promise middleware will now change the name of our actions, for example assuming ActionType.Query (in the code earlier) is the string “QUERY” then the promise middleware suffixes this string with _PENDING (when the promise is first returned), _FULFILLED (when the promise successfully completes) and _REJECTED (when the promise fails, i.e. an error).

So it’s easy to write the following to use in the redux switch

const PENDING = actionType => `${actionType}_PENDING`;
const FULFILLED = actionType => `${actionType}_FULFILLED`;
const REJECTED = actionType => `${actionType}_REJECTED`;

Now our switch case statements might look like this

case PENDING(ActionType.Query):
   return {
      ...state,
      queryError: undefined,
      runningQuery: true
   };
case FULFILLED(ActionType.Query):
   return {
      ...state,
      queryResult: action.payload,
      runningQuery: false
   };  
case REJECTED(ActionType.Query):
   return {
      ...state,
      queryError: action.payload,
      runningQuery: false
   };  

In the above the PENDING action type will occur first, so we’ll ensure any error is cleared and set a property which we bind a progress indicator in the UI. If the promise fails, REJECTED is called and we could assign some error data to our store for displaying to the user, obviously FULFILLED is called when a successful completion occurs.

Updating React Component state from props

There comes a time when the state we’re storing within our React Component needs to be updated, for example I have a ToggleButtonGroup which stores the state for the currently pressed/selected child item (i.e. you press a button in the group and the other’s deselect etc. basically a radio button).

When the component is created we might set our state from the properties like this

constructor(props) {
   super(props);

   this.state = { selected: this.props.selected }    
}

but the constructor is not called again, so what if our container component needs to change the state in our ToggleButtonGroup, so that when the properties are updated so that the ToggleButtonGroup reflects the property changes in the state.

Note: without some code in place to handle prop to state synchronisation will likely have state out of sync with expected values/behaviour.

We can use the componentDidUpdate function like this to update our state

componentDidUpdate(prevProps) {
   if(this.props.selected != prevProps.selected) {
      this.setState({selected: this.props.selected});
   }  
}

This occurs after the properties have been updated. See componentDidUpdate for more information.

You should have the guard to only change the state if the property actually changed.

componentDidUpdate is not called

The likely reason that the componentDidUpdate function is not called is if shouldComponentUpdate returns false.

getDerivedStateFromProps

An alternative to componentDidUpdate is to write a static function named getDerivedStateFromProps into your components/class. This is invoked before the render function for both initial and subsequent updates. I’ve not used this so best to read more at getDerivedStateFromProps.

Deprecated method

This method has been deprecated, but in case you come across it, we can use the component lifecycle function componentWillReceiveProps to achieve the same synchronisation of props to state. For example

componentWillReceiveProps(newProps) {
   if(newProps.selected != this.props.selected) {
      this.setState({selected: newProps.selected});
   }
}

PropTypes

PropTypes are used in React components to specify type information etc. If (as I am) you’re using TypeScript then for the most part such type extra information is not really required as we get a similar functionality via TypeScript interfaces. However, you’ll see these used a lot in JSX files where. not only can you define the expected types, but also the expected values.

To install

yarn add prop-types

PropTypes are only available in development mode which makes sense for the most part, so you would still need runtime checking on values supplied by the end user or the likes.

The usual way to write our propTypes in a JSX file is like this

import React from 'react';
import PropTypes from 'prop-types';

class Company extends React.Component {
    render() {
        return <div> 
        <h1>{this.props.name}</h1>
        {this.props.country ? <p>Country: {this.props.country}</p> : null}
        {this.props.size ? <p>Size: {this.props.size}</p> : null}
        </div>;   
    }
}

Company.propTypes = {
  name: PropTypes.string,
  country: PropTypes.string,
  size: PropTypes.oneOf(['small', 'medium', 'large']),
};

export default Company;

If we now change App.tsx to just have this

const App: React.FC = () => {
  return (
    <Company name="My Company" size="mega" />
  );
}

You’ll find this runs but an error log in your preferred browser debug tools will show that “maga” is not a valid option, because obviously it wasn’t oneOf the supplied options.

Let’s now change the Company.jsx file to a .tsx extension.

This will fail to transpile with an error such as “Type ‘{ name: string; size: string; }’ is not assignable to type ‘IntrinsicAttributes & IntrinsicClassAttributes & Readonly<{}> & Readonly<{ children?: ReactNode; }>‘.”

Instead, we can use interfaces within TypeScript to handle the type checking at transpile time, hence this code gives us a similar set of function to the JSX version

type Size = 'small' | 'medium' | 'large';

interface CompanyProps {
  name?: string,
  country?: string,
  size?: Size
}

class Company extends React.Component<CompanyProps> {

    render() {
        return <div> 
        <h1>{this.props.name}</h1>
        {this.props.country ? <p>Country: {this.props.country}</p> : null}
        {this.props.size ? <p>Size: {this.props.size}</p> : null}
        </div>;   
    }
}

References

prop-types
ts-proptypes-transformer

Code editor for React

This is a quick post to say, if you’re looking for a JavaScript code editor UI for your application, the react-ace editor has so far proven itself very useful.

Install via yarn add react-ace and you’ll also want yarn add brace for themes, syntax colour.

Now import the dependencies like this

import AceEditor from "react-ace";
import "brace/mode/javascript";
import "brace/mode/python";
import "brace/theme/monokai";
import "brace/theme/github";

This includes two themes, monokai and GitHub for you to try along with two language colourings, in the form of javascript and python.

Now to use the editor, just drop the following code into your application

<AceEditor mode="python" //javascript
  theme="github" //monokai
  width="100%"
  onChange={this.handleOnChange}
  name="AceEditor"
  editorProps={{$blockScrolling: true}}
  value={code}
  fontSize={16}
/>          

In this example we’d have an onChange handler to store the changed text in from the editor, the value={code} is the source code that is initially displayed.

React and CSS

Standard approach to CSS

In a previous post we looked at an animated button and the issue(s) of having CSS in a separate .css file.

To recap, CSS can be implemented in a standalone .css file, for example AniButton.css might look like this (this is an abridged version of the CSS used in the previous post)

.button {
  background: #2B2D2F;
  height: 80px;
  width: 200px;
  text-align: center;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  left: 0;
  right: 0;
  margin: 0 auto;
  cursor: pointer;
  border-radius: 4px;
}

This can then be imported into our React jsx/tsx file using

import "AniButton.css"

and everything works as per standard CSS. A couple of downsides to this are the CSS is in global namespace and also we’re using another language/DSL to define CSS whereas, it’d be nice if we could do all this in one language, i.e. in this case JavaScript/TypeScript.

Inline the style

From this global approach we can look towards inline of the CSS and also at the same time, removing the different language/DSL issue by declaring CSS in a JavaScript JSON style object, for example we remove the .CSS file and it’s import and then include the CSS style as an object, like this

const styles = {
  button: {
    background: "#2B2D2F",
    height: "80px",
    width: "200px",
    textAlign: "center",
    position: "absolute",
    top: "50%",
    transform: "translateY(-50%)",
    left: "0",
    right: "0",
    margin: "0 auto",
    cursor: "pointer",
    borderRadius: "4px"
  }
};

to apply this style we will need to add a style attribute to each of the elements we want a style applied to, for example

<div className="button" style={styles.button}>
</div>

One obvious downside of this inclusion of CSS along with our code is the separation of concerns might be seen as being lost, i.e. styling is now included along with the component code, however I tend to see React as lacking that separation of markup and code which you get with something like XAML/WPF, so I suppose it’s simply down to your interpretation of such things.

Styled components

Another solution which is a bit of a combination of CSS (syntax wise the names do not change to camelCase nor are values wrapped in quotes) and JavaScript is to use a library such as styled-components or emotion.

I’m going to look at Emotion’s implementation, so run the following

yarn add @emotion/styled @emotion/core

Now we can replace our button CSS and inline JavaScript CSS with style components, for example within your JSX/TSX file implement the following

import styled from '@emotion/styled'

const Button = styled.div`
  background: #2B2D2F;
  height: 80px;
  width: 200px;
  text-align: center;
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  left: 0;
  right: 0;
  margin: 0 auto;
  cursor: pointer;
  borderRadius: 4px;
`;

Now in usage our code looks like this

<Button className="button" onClick={this.handleOnClick}>
  <div className="text" style={styles.text} onClick={this.handleOnClick}>Submit</div>
</Button>

Converting animated button to React

I was looking at a nice little animation of a button on https://codepen.io/andrewmillen/pen/MoKLob and thought it’d be interesting turning it into a React component especially as I’m currently playing with animejs. As usual such things never “just work” but that also means it’s a good learning process.

So here goes, first off create your React application and add the animejs library…

  • yarn create react-app animatedbutton –typescript

From within the generated application run the following

  • yarn add animejs
  • yarn add @types/animejs

Note: I will not list all the code here, it’s available on GitHub, but I’ll list the changes and things of interest.

Next create a components folder off of the src folder and create AniButton.css, copying the CSS from the original link into that and then create AniButton.jsx which I’ve included here

Note: I used a jsx file as opposed to tsx simply because I didn’t want to spend too long fixing “type” issues initially, but when I did try this I found the ref is not expected on a path element, so we’ll stick with JSX for now.

export class AniButton extends React.Component {

  checkRef = React.createRef();

  constructor(props) {
    super(props);

    this.handleOnClick = this.handleOnClick.bind(this);
  }

  handleOnClick() {

    var pathEls = this.checkRef.current;
    var offset = anime.setDashoffset(pathEls);
    pathEls.setAttribute("stroke-dashoffset", offset);

    var basicTimeline = anime.timeline({
      autoplay: false
    })
    .add({
      targets: ".text",
      duration: 1,
      opacity: 0
    })
    .add({
      targets: ".button",
      duration: 1300,
      height: 10,
      width: 300,
      backgroundColor: "#2B2D2F",
      border: "0",
      borderRadius: 100
    })
    .add({
      targets: ".progress",
      duration: 2000,
      width: 300,
      easing: "linear"
    })
    .add({
      targets: ".button",
      width: 0,
      duration: 1
    })
    .add({
      targets: ".progress",
      width: 80,
      height: 80,
      delay: 500,
      duration: 750,
      borderRadius: 80,
      backgroundColor: "#71DFBE"
    })
    .add({
      targets: pathEls,
      strokeDashoffset: [offset, 0],
      opacity: 1,
      duration: 200,
      easing: "easeInOutSine"
    });

    basicTimeline.play();
  }

  render() {
    return (
      <main>
        <div className="button" onClick={this.handleOnClick}>
          <div className="text" onClick={this.handleOnClick}>Submit</div>
        </div>
        <div className="progress"></div>
        <svg x="0px" y="0px"
          viewBox="0 0 25 30">
          <path ref={this.checkRef} className="check st0" d="M2,19.2C5.9,23.6,9.4,28,9.4,28L23,2" />
        </svg>
      </main>
    )
  }
}

Note: A couple of changes I made to the CSS was change the progress bar name and fixed the background to gray. The reason I did this was simply because I had problems initially with the CSS displaying incorrectly and messed with things to try to resolve – I think the problem is unrelated to the changes I made though.

Also I seem to periodically lose the progress bar, not 100% why but just saying.

The key differences to the original source code are – obviously it’s coded into a React.Component. Event handlers are within the class, but really the main difference is the way we get access to the DOM path element via the ref={this.checkRef}. I’ve removed the loop from the original code which found the paths as we only have one here.

Next, the original code uses the Poppins font, so add the following the public/index.html

<link 
   href="https://fonts.googleapis.com/css?family=Poppins:600" 
   rel="stylesheet">    

The animejs code

At this point everything works nicely, so let’s look at the animejs code.

We need to get a reference to the DOM path object using

var pathEls = this.checkRef.current;
var offset = anime.setDashoffset(pathEls);
pathEls.setAttribute("stroke-dashoffset", offset);

The anime.setDashoffset code does the following

“Creates path drawing animation using the ‘stroke-dashoffset’ property. Set the path ‘dash-offset’ value with anime.setDashoffset() in a from to formatted value.”

Next we create an animejs, which basically allows us to coordinate each stage/step of the animation. Hence the first timeline is to immediately hides the .text using the opacity property and a very short duration.

Now we change the shape of the .button to a thinner button etc.

The next step is to display a progress overlay which starts from the centre (based upon the CSS) and expands out over it’s duration in a linear easing.

Once the previous step’s completed which reduce the .button to zero width to basically hide it and the .progress then changes colour and eventually turns into a circle.

Finally the check/tick is displayed using the strokeDashOffset, so basically this animates the drawing of the check.

CSS

For the most part the animejs timeline code is pretty simple and works a treat, so let’s take a look at the CSS side of things.

Firstly we can import the CSS using

import "./AniButton.css";

Which basically tells webpack (in a standard React application) to include the CSS in the bundle. Now the CSS can be applied to our elements in the usual ways, on an element type or via id or class (in React class becomes classname).

As stated previously though, if you require actual access into the DOM you’ll need to use something like a ref, but use sparingly.

CSS files like the ones we’re using are not really the preferred way to use CSS in React (see the React: CSS in your JS by Christopher Chedeau for some reasons why this is the case, admittedly it’s a few years old but still relevant now).

To save you watching the video, CSS files defines CSS globally which can make styling difficult to debug or understand at times. Also it’s equally difficult to know when CSS is redundant, i.e. an element s no longer used but we still maintain it’s CSS etc.

I’m not going to go into all the others ways to use CSS it this post, but obviously our best way to use CSS would be to have it used locally inlined with our component.

Hence we can instead convert our CSS to the following code within our AniButton.jsx file like this

const styles = {
  main: {
    height: "100vh",
    width: "100vw"
  },
  button: {
    background: "#2B2D2F",
    height: "80px",
    width: "200px",
    textAlign: "center",
    position: "absolute",
    top: "50%",
    transform: "translateY(-50%)",
    left: "0",
    right: "0",
    margin: "0 auto",
    cursor: "pointer",
    borderRadius: "4px"
  },
  text: {
    font: "bold 1.25rem/1 poppins",
    color: "#71DFBE",
    position: "absolute",
    top: "50%",
    transform: "translateY(-52%)",
    left: "0",
    right: "0"
  },
  progress: {
    position: "absolute",
    height: "10px",
    width: "0",
    right: "0",
    top: "50%",
    left: "50%",
    borderRadius: "200px",
    transform: "translateY(-50%) translateX(-50%)",
    background: "gray",
  },
  svg: {
    width: "30px",
    position: "absolute",
    top: "50%",
    transform: "translateY(-50%) translateX(-50%)",
    left: "50%",
    right: "0",
    enableBackground: "new 0 0 25 30"
  },
  check: {
    fill: "none",
    stroke: "#FFFFFF",
    strokeWidth: "3",
    strokeLinecap: "round",
    strokeLinejoin: "round",
    opacity: "0"
  }   
}

Note: underline or hyphens turn into camelCase names and values get wrapped in quotes.

Now we will need to explicitly add the styles to our render code using style={} syntax, so it looks like this

<main style={styles.main}>
  <div className="button" style={styles.button} 
       onClick={this.handleOnClick}>
     <div className="text" style={styles.text} 
       onClick={this.handleOnClick}>Submit</div>
  </div>
  <div className="progress" style={styles.progress}></div>
  <svg x="0px" y="0px"
    viewBox="0 0 25 30" style={styles.svg}>
    <path ref={this.checkRef} style={styles.check} 
      className="check st0" d="M2,19.2C5.9,23.6,9.4,28,9.4,28L23,2" />
  </svg>
</main>

We can now delete our AniButton.css file.