Welome to C4GT’s React Cheetsheet here you will find everything to start with React.
Check prereq
Command | Notes |
---|---|
npx create-react-app {app name} | Create new React app |
npm run build | Build React app - create a folder with files ready for deployment |
npm start | Run project locally |
npm test | run tests in React app |
npm eject | remove the single build dependency from your project |
JSX allows us to write HTML elements in JavaScript and place them in the DOM. Basically, it converts HTML tags into react elements.
const value = 'Hello world';
return (<div>{value}</div>);
‘Hello world’ will be injected and displayed inside <div>
element
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 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.
const avatarUrl = "img/picture.jpg"
const element = <img src={avatarUrl}></img>;
JavaScript code can be also called for DOM element properties/events
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>
</>
We can refer to html element from JS
this.element = React.createRef();
<div ref={this.element}></div>
3. Use reference to interact with element
```js
this.element.current.focus();
Tip: References works for the class component but not for function component (unless you use useRef hook, see Other hooks )
“React lets you define components as classes or functions. Components defined as classes currently provide more features”
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" />
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" />
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:
this.onClick = this.onClick.bind(this);
_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
}
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>}
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 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>
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
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
Parent:
<Route path="/some" component={SomeComponent}></Route>
SomeComponent:
function SomeComponent({ match }) {
return (
<Router>
<Switch>
<Route path={`${match.path}/child`}><Child /></Route>
</Switch>
</Router>
)
}
<Route path="/some/:id" component={SomeComponent}></Route>
and then in SomeComponent we have access to:
{match.params.id}
Good idea is to create a custom Route component that will show specific component only when our authentication logic is passed:
Then instead of Route use PrivateRoute
<PrivateRoute path="/list" component={List}></PrivateRoute>
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 | Notes |
---|---|
componentDidMount | Called at the beginning of component life - when a component has been rendered |
componentWillUnmount | This method is called before the unmounting of the component takes place. |
componentWillUpdate | Before re-rendering component (after change) |
componentDidUpdate | After re-rendering component (after change) |
componentDidCatch | Called when an error has been thrown |
shouldComponentUpdate | Determines whether a component should be updated after a change or not |
getDerivedStateFromProps | Called at the beginning of component life and when props/state will change |
getSnapshotBeforeUpdate | Called just before rerendering component - in order to save state |
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
}
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
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');
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");
});
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);
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()
Example:
jest.mock("./SomeComponent", () => {
return function DummyComponent(props) {
return (
<div data-testid="square">
here is square
</div>
);
};
});
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 let us use in functions React features dedicated previously for only classes, like state.
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);
Hook | Usage | Notes |
---|---|---|
useReducer | const [state, dispatch] = useReducer(reducer, initialArg, init); | Used for redux |
useCallback | const memoizedCallback = useCallback(() => {doSomething(a, b);},[a, b],); | Returns a memoized callback |
useMemo | const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]); | Returns a memoized value. |
useRef | const refContainer = useRef(initialValue); | Hooks for element reference |
useDebugValue | useDebugValue(value) | Display information in React DevTools |
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];
}
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
declare namespace JSX {
interface IntrinsicElements {foo: any}
}
<foo />; // ok
<bar />; // error
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.