React Cheat Sheet

Basic React commands

JSX

JSX allows us to write HTML elements in JavaScript and place them in the DOM. Basically, it converts HTML tags into react elements.

Injection JS into HTML

 const value = 'Hello world';
 return (<div>{value}</div>);

'Hello world' will be injected and displayed inside <div> element

Element declaration

 const value = 'Hello World';
 const element = <div className="App">{value}</div>;
 return (element);

We can assign specific DOM fragments to a particular variable (element above) and then (re)use it everywhere.

Function injection

 function addNumbers(x1, x2) {
   return x1 + x2;
 }
 const element = <div className="App">{addNumbers(2, 5)}</div>

Not only string values can be injected into DOM. The result of the above case will be div with 7 inside it as addNumbers was injected into an element.

Attributes

  const avatarUrl = "img/picture.jpg"
  const element = <img src={avatarUrl}></img>;

JavaScript code can be also called for DOM element properties/events

Fragments

JSX syntax must have one top parent HTML element. When we don't want to pack our HTML into (for example) one div or other elements then we can use fragment which won't be rendered in our HTML

Example:

<React.Fragment>
   <td>val1</td>
   <td>val2</td>
</React.Fragment>

or

<>
  <td>val1</td>
  <td>val2</td>
</>

References

We can refer to html element from JS

  1. Declare a reference

this.element = React.createRef();
  1. Assign a reference to element

<div ref={this.element}></div>
  1. Use reference to interact with element

this.element.current.focus();

Tip: References works for the class component but not for function component (unless you use useRef hook, see Other hooks )

Components

"React lets you define components as classes or functions. Components defined as classes currently provide more features"

Function component

Sample component:

function App() {
  return <div>Hello World</div>;
}
export default App;

Sample component with parameters:

function Welcome(props) {
    return <h1>Hello, {props.name}</h1>;
}
<Welcome name="Sara" />

Class component

Sample component:

class App extends React.Component  {
  render() {
    return <div>Hello World</div>;
  }
}
export default App;

Sample component with the parameters:

class Welcome extends React.Component  {
  render() {
    return <div>Hello {this.props.name}</div>;
  }
}
export default App;
<Welcome name="Sara" />

Events

Sample onClick event in an element:

<a href="#" onClick={this.onClick}> Click me </a>

onClick function:

onClick(e) {
    e.preventDefault();
    // some logic here
}

Access to "this" inside event:

There are a few ways to achieve that:

  1. bind this

this.onClick = this.onClick.bind(this);
  1. Arrow function. For arrow function, you don't have to perform binding because arrow functions are performing this binding by themselves by referring to this with _this variable _this = this

onClick = (e) => {
    e.preventDefault();
    console.log(this);
}

or

 <a href="#" onClick={(e) => this.onClick(e)}> Click me</a>

Child event

We can call a function in parent component from the child component.

Child component (somewhere in code):

this.props.onChange(val1, val2,...)

Parent component:

 <Child onChange={hasChanged} />
function hasChanged(val1, val2,...) {
 // some logic here
}

Conditional element

Show element depending on the implemented condition

Option 1:

function SomeElement(props) {
   const show = props.isShowed;
   if(show) {
      return <div>Here is element</div>;
   }         
}

then:

<SomeElement isShowed = {true} />

Option 2:

let element;      
if(this.state.isShown) {
    element  = <div> Here is element </div>;
} 

and then use the element variable in jsx

Option 3:

{this.state.isShow  ?  <div> Here is element </div> : 'No element'}

Option 4:

{this.state.isShow  &&  <div> Here is element </div>}

List of elements

The recommended way to show a list of the same components is to use the "map" function. Example:

const numbers = [1, 2, 3, 4, 5];
const listItems = numbers.map((numer, index) =>
  <li key={number.toString()}>
    {number}
  </li>
);

Then just use listItems element in your JSX DOM. Please note key property inside - it is obligatory to identify particular row in list.

Content projection

Content projection is injecting some HTML from parent component to child component

Example:

Parent component:

<MyElement><h1>Hello world</h1></MyElement>

Child (MyElement) component:

<div>
   {this.props.children}
</div>

<h1>Hello world</h1> will be injected to place where {this.props.children} has been used, so MyElement will look like:

<div>
   <h1>Hello world</h1>
</div>

Higher order component

Create a parameterized component in order to reuse it in different ways.

Example:

const myHoc = settings => WrappedComponent => {
    return class DecoratingComponent extends React.Component {
        render() {
            return (<div className={settings}><WrappedComponent {...this.props} /></div>)
        }
    }
}

Usage:

const MyWrappedComponent = myHoc('test')(SomeComponent);
<MyWrappedComponent/>

test will be injected into className

Routing

The Router will be described with react-router-dom library usage, which is often recommended.

Install:

npm install react-router-dom 

Sample presenting an area where components matching to current URL will be rendered:

<Router>
   <Switch>
     <Route path="/help"><Help /></Route>
     <Route path="/list"><List /></Route>
     <Route path="/"><Home /></Route>
   </Switch>
 </Router>

Link changing current url:

<Link className="nav-link" to="/list">List</Link>

Tip: Route and Link need to be in same Router element

Nested routing

Parent:

<Route path="/some" component={SomeComponent}></Route>

SomeComponent:

function  SomeComponent({ match }) {
    return (
        <Router>
            <Switch>
                <Route path={`${match.path}/child`}><Child /></Route>
            </Switch>
        </Router>
    )
}

Routing with parameters

<Route path="/some/:id" component={SomeComponent}></Route>

and then in SomeComponent we have access to:

{match.params.id}

Authentication

Good idea is to create a custom Route component that will show specific component only when our authentication logic is passed:

function PrivateRoute({ component: Component, ...rest }) {
    return (
        <Route {...rest} render={(props) => (_isAuthentictedLogic_) ?
            (<Component {...props} />) :
            (<Redirect to={{ pathname: "/noAccess", state: { from: props.location } }} />
            )}
        />
    );
}

Then instead of Route use PrivateRoute

<PrivateRoute path="/list" component={List}></PrivateRoute>

State and life cycle

State

The state decides about the update to a component’s object. When state changes, the component is re-rendered.

Declaring initial state:

constructor() {
    this.state = { userId: 2, userName: "Jannice"};
}

Using state:

<div> {this.state.userName} </div>

Updating state:

this.setState({ userId: 3, userName: "Tom"});

After setState component will be re-rendered

Life cycle

Note Deprecation alert for componentWillUnmount and componentWillUpdate. This can cause memory leaks for server rendering.

Example:

componentDidMount() {
    console.log("componentDidMount")
    // some logic here
}

componentWillUnmount() {
    console.log("componentWillUnmount")
    // some logic here
}

Forms

Sample form:

onValueChange  = (event) => {
    this.setState({ value:  event.target.value  });
}
onSubmit = (e) => {
	e.preventDefault();
	// Submit logic
}
<form onSubmit={this.handleSubmit}>
    <input type="text"
        value={this.state.value}
        onChange={this.onValueChange}
    />
    
    <input type="submit" value="Send" />
</form>

Validation is described here: https://webfellas.tech/#/article/5

Http requests

There are a lot of ways to communicate with our backend API. One of them is to use Axios library.

Install: npm install axios

Example with GET:

axios.get('/user', {
params: {ID: 12345}
}).then(function (response) {
   //some logic here
})
.catch(function (error) {
   //some logic here
})
.finally(function () {
   //some logic here
}); 

Example with POST:

axios.post('/user', {
    firstName: 'Fred',
    id: 2
}).then(function (response) {
    //some logic here
})
.catch(function (error) {
    //some logic here
});

Example with async call:

const response = await axios.get('/user?ID=12345');

Tests

Useful libs:

npm install --save-dev jest to run tests

npm install --save-dev @testing-library/react set of functions that may be useful for tests in React

Sample tests:

let container = null;
beforeEach(() => {
  container = document.createElement("div");
  document.body.appendChild(container);
});
afterEach(() => {
  unmountComponentAtNode(container);
  container.remove();
  container = null;
});
it("renders menu with Help", () => {
  act(() => {
    render(<Router><SomeComponent /></Router>, container);
  });
  expect(container.textContent).toBe("Some text inside");
});

Interaction

Click on element:

import { fireEvent } from '@testing-library/react'
fireEvent.click(container.querySelector('.some-class));

Change value in input:

fireEvent.change(container.querySelector('.some-class)), {
    target: { value: "12345" }
});

Check if element contains class

expect(someEl.classList.contains('disabled')).toBe(false);

Mocking http

npm install axios-mock-adapter --save-dev

Example:

var axios = require('axios');
var MockAdapter = require('axios-mock-adapter');
var mock = new MockAdapter(axios);
mock.onGet('/users').reply(200, {
  users: [
    { id: 1, name: 'John Smith' }
  ]
});

With specific parameter

mock.onGet('/users', { params: { searchText: 'John' } }).reply()

Mocking components

Example:

jest.mock("./SomeComponent", () => {
  return function DummyComponent(props) {
    return (
      <div data-testid="square">
        here is square
      </div>
    );
  };
});

Context

Context is a "bag" for some data common for node of components.

Declare context:

import React from 'react';
export const ColorContext = React.createContext('red');

'red' is default value

Create context and distribute it to child component:

const { Provider } = ColorContext;
return (
    <Provider value={this.state.color}>
    	<SomeComponent />
    </Provider>
);

Use it in child component:

const { Consumer } = ColorContext;
return (
   <Consumer>
	{value => <div>{value}</div>}
   </Consumer>
)

Use it in child component outside render function:

static contextType = ColorContext;
let value = this.context.value

Hooks

Hooks let us use in functions React features dedicated previously for only classes, like state.

Basic hooks

useState hook

Can replace state managment

const [count, setCount] = useState(0);

count can be used to read data

0 is the default value for count

setCount(10) is a function to change count state value

useEffect hook

Can replace componentDidMount, componentDidUpdate, componentWillUnmount and other life cycle component events

Instead of using componentDidMount, componentDidUpdate we can use useEffect hook like this:

useEffect(() => {
    document.title = `Clicked ${count}`;
});

In order to act as componentWillUnmount:

useEffect(() => {
    return () => {/*unsubscribe*/};
});

useContext hook

Hooks for context implementation. See Context

Parent:

const CounterContext = React.createContext(counter);

function App() {
  return (
    <CounterContext.Provider value={10}>
      <ChildComponent />
    </CounterContext.Provider>
  );
}

Child:

const counter = useContext(CounterContext);

Other hooks

Custom hook

Custom hooks can be created. Sample implementation:

function useColor(initialColor) {
    const [color, changeColor] = useState(initialColor);
    function change(color) {
        changeColor(color);
    }
    useEffect(() => {
        console.log('Color changed');
    });
    return [color, change];
}

TypeScript in React

Add to project commands

npx create-react-app my-app --typescript - new app with TypeScript

npm install --save typescript @types/node @types/react @types/react-dom @types/jest - add TypeScript to existing project

npx tsc --init - init tsconfig

Add type for custom DOM element

declare namespace JSX {
    interface IntrinsicElements {foo: any}
}
<foo />; // ok
<bar />; // error

Interview questions

Q: How can we declare the component??

A: Use class extending React.Component or use function with React.FC type returning JSX.

Q: What is a difference between function component and class component?

A: Components defined as classes currently provide more features. Anyway, hooks can change that.

Q: In what type of component can we use hooks?

A: Function component

Q: How can we inject some HTML from parent component to child component?

A: Using content projection - > this.props.children will keep parent html element. See Content projection

Q: Describe useEffect hook

A: UseEffect can replace componentDidMount, componentDidUpdate, componentWillUnmount and other life cycle component events. See Basic hooks

Q: What is the difference between state and props??

A: The state decides about the update to a component’s object. When state changes, the component is re-rendered. Props are parameters passed from parent component to child component.

Q: What is a higher-order component??

A: Basically its's parameterized component. It allows reusing of a particular component in many ways. Sample implementation:

const myHoc = settings => WrappedComponent => {
    return class DecoratingComponent extends React.Component {
        render() {
            return (<div className={settings}><WrappedComponent {...this.props} /></div>)
        }
    }
}

usage:

const MyWrappedComponent = myHoc('test')(SomeComponent);
<MyWrappedComponent/>

Q: What is JSX?

A: JSX allows us to write HTML elements in JavaScript and place them in the DOM. Basically, it converts HTML tags into react elements. See JSX

Q: How can we create new react app?

A: Using command npx create-react-app {app name}

Q: What will be the result of npm eject?

A: Webpack for React application won't be handled automatically anymore. We will have access to Webpack configuration files in order to customize it to our needs.

Last updated