Перейти к основному содержимому

React

Components​

Simple Component​

React components implement a render() method that takes input data and returns what to display. This example uses an XML-like syntax called JSX. Input data that is passed into the component can be accessed by render() via this.props.

class HelloMessage extends React.Component {
render() {
return <div>Hello {this.props.name}</div>;
}
}

ReactDOM.render(
<HelloMessage name="Rick" />,
document.getElementById('hello-example')
);

Stateful Components​

In addition to taking input data (accessed via this.props), a component can maintain internal state data (accessed via this.state). When a component’s state data changes, the rendered markup will be updated by re-invoking render().

class Timer extends React.Component {
constructor(props) {
super(props);
this.state = { seconds: 0 };
}

tick() {
this.setState(state => ({
seconds: state.seconds + 1
}));
}

componentDidMount() {
this.interval = setInterval(() => this.tick(), 1000);
}

componentWillUnmount() {
clearInterval(this.interval);
}

render() {
return <div>Seconds: {this.state.seconds}</div>;
}
}

ReactDOM.render(<Timer />, document.getElementById('timer-example'));

UseEffect & UseState Hook​

Hooks are a new addition in React 16.8. They let you use state and other React features without writing a class. The Effect Hook lets you perform side effects in function components. The State Hook lets you manage state in a functional component.

Here is the above code snippet, using Hooks:

function Timer(props) {

// declare your state variable, a function to modify it, and set an initial value
const [seconds, setSeconds] = useState(0);

const tick = () => {
setSeconds(seconds + 1);
}

useEffect(() => {
const interval = setInterval(() => {
// this will run every second!
tick();
}, 1000);
// you can return a 'clean up' function which will run when the component unmounts
return () => clearInterval(interval);
}, []);

return (
<div>
Seconds: {seconds}
</div>
);
}

ReactDOM.render(
<Timer />,
document.getElementById('timer-example')
);

Context Provider Component​

Context is a way or providing global state to a React application. There are two parts to Context, a Provider and a Consumer. A Context Provider Component allows all components rendered inside to access the value passed.

import React, { createContext } from 'react';

const MyContext = React.createContext(defaultValue);

class ContextProvider extends React.Component {
state = {
key: 'value'
};
render() {
return (
<MyContext.Provider value={this.state}>
{this.props.children} // all children can access value using a consumer
or useContext
</MyContext.Provider>
);
}
}

export default ContextProvider;

Context Consumer Component​

Context is a way or providing global state to a React application. There are two parts to Context, a Provider and a Consumer. The Context Consumer component allows access to the value in the provider via a 'render prop' pattern.

import React from 'react';

import MyContext from '../ContextProvider';

class AnyComponent extends React.Component {
render() {
return (
<MyContext.Consumer>
{value => {
return <p>now we can render the {value}</p>;
}}
</MyContext.Consumer>
);
}
}

export default AnyComponent;

Context Provider Component with useState Hook​

Here we use a similar context example as above. However instead of using a class based component, we use a functional component with the useState hook.

import React, { createContext, useState } from 'react';

export const MyContext = createContext();

export const ContextProvider = props => {
const [state, setState] = useState({ key: 'value' });
return (
<MyContext.Provider value={{ state, setState }}>
{props.children}
</MyContext.Provider>
)
}

useContext Hook​

Context is a way or providing global state to a React application. There are two parts to Context, a Provider and a Consumer. The useContext hook allows access to the value in function components.

import React, { useContext } from 'react';

import MyContext from '../ContextProvider';

const AnyFunctionComponent = () => {
const value = useContext(MyContext);
return <p>now we can render the {value}</p>;
};

export default AnyFunctionComponent;

Functional Components​

Functional components are the simplest way to write components in React. They don't hold state, they don't fire lifecycle events; they simply take props and render a React Element.

function MyComponent ({ name }) {
return <div className='message-box'>
Hello {name}
</div>
}

Functional Components can be written with arraow functions.

const Greeting = (props) => 
<h1> Hello {props.name} </h1>;

ReactDOM.render() {
<Greeting name="xyz" />;
document.getElementById("root");
};

Hooks in Combination with setInterval()​

In comparison to stateful components in React, hooks let you use features like state without the neccessity of writing a class compoent.

function useInterval(callback) {
const savedCallback = useRef();

useEffect(() => {
savedCallback.current = callback;
}, [callback]);

useEffect(() => {
const id = setInterval(() => savedCallback.current(), 1000);
return () => clearInterval(id);
});
}

function Timer() {
const [seconds, setSeconds] = useState(0);

useInterval(() => setSeconds(seconds + 1));

return (
<div>
Seconds: {seconds}
</div>
);
}

ReactDOM.render(
<Timer />,
document.getElementById("timer-example")
);

User Input Components​

As the user types into the input field, we will store the input in our Component State and display it on the screen.

import React, { Component } from 'react';

class InputField extends Component {
state = {
userInput: ''
}

handleChange = (e) => {
this.setState({
userInput: e.target.value
})
}

render() {
return (
<div style={{paddingLeft: '5%'}}>
<input onChange={(e) => this.handleChange(e)}type="text" />
<p><strong>You have typed:</strong> {this.state.userInput}</p>
</div>
);
}
}

export default InputField;

setState() Best Practices​

The most common confusion in using React is setState() function, Here's some tips on how to use setState() properly.

class Lock extends React.Component {
constructor(props) {
super(props);
this.state = { locked: false };
}
unlock = () => {
// we can access previous state via passing function
this.setState(state => ({
locked: !state.locked
}));
}
lock = () => {
// setState is an asynchronous function, so that there are times that, it can't return the mutate state
// immediately, but using the second parameter in setState(), you can now access the new state value.
this.setState({locked: true}, () => {
console.log(this.state.locked);
})
}

combinedSetState = () => {
// We can actually combined this ways :)
this.setState(state => ({
locked: !state.locked
}), () => {
console.log(this.state.locked);
})
}
componentDidMount() {
this.unlock()
}
render() {
return (
<div>
Is locked: {this.state.locked}
</div>
);
}
}
ReactDOM.render(
<Lock />,
document.getElementById('lock')
);

Hook for throttling value change​

A custom hook to help throttling changes to variables. Especially useful when automatically queriying api's based on user text-input

import { useState, useEffect, useRef } from 'react';

const useThrottle = (value, limit = 300) => {
const [throttledValue, setThrottledValue] = useState();
const lastRan = useRef(Date.now());

useEffect(() => {
const handler = setTimeout(() => {
if (Date.now() - lastRan.current >= limit) {
setThrottledValue(value);
lastRan.current = Date.now();
}
}, limit - (Date.now() - lastRan.current));

return () => {
clearTimeout(handler);
};
}, [value, limit]);

return throttledValue;
};

Hook for debouncing value change​

A similar custom hook to help debouncing changes to variables.

import { useState, useEffect } from 'react';

function useDebounce(value, delay) {
const [debouncedValue, setDebouncedValue] = useState(value);
useEffect(() => {
const handler = setTimeout(() => {
setDebouncedValue(value);
}, delay);
return () => {
clearTimeout(handler);
};
}, [delay, value]);
return debouncedValue;
}

Rendering your react component to the DOM​

Render your react element into the DOM. The id belongs to the element in which the react application will mount.

import React from 'react'
import ReactDOM from 'react-dom'

import App from './app'

ReactDOM.render(<App />, document.getElementById('foo-bar'))

Rendering component for each array item​

Let's supose that you have to create component that renders a job list.

  1. JobContent component
const JobContent = ({ children }) => (
<ul>
{children}
</ul>
);
export default JobContent;
  1. JobItem component
const JobItem = ({{name}}) => (
<li>
<h4{name}</h4>
</li>
);
export default JobItem;
  1. Map
const renderJobItems = jobs => {
jobs.map(jobItem => (
<JobItem name={jobItem.name} />
));
}
const RenderJobs = ({jobs}) => (
<JobContent>
{renderJobItems(jobs)}
</JobContent>
)
export const RenderJobs;
  1. Just pass jobs array to RenderJobs
const jobs = ['Software Engineer', 'Tech Recruiter']
<RenderJobs jobs={jobs} />
);

Using Refs to access DOM properties​

class MyComponent extends Component {
componentDidMount() {
this.input.focus();
}
render() {
return (
<div>
<input ref={el => (this.input = el)} />
</div>
);
}
}

Create a list by passing an array​

class AnimalsList extends Component {
render() {
const { animals } = this.props.animals; // Array of animals

return (
<ul>
{animals.map(animal => (
<Animal name={animal} key={animals.key} />
))}
</ul>
);
}
}

Create an element without using JSX​

React.createElement("div", { className: "maindiv" });