From 4b9f46bac19e216f3cebffb0bfdf77b7353ee81b Mon Sep 17 00:00:00 2001 From: Sumsum1231 Date: Fri, 14 Jun 2024 13:55:37 +0530 Subject: [PATCH] feat: React Cheetsheet --- Frameworks-or-Libraries/React.md | 868 +++++++++++++++++++++++++++++++ 1 file changed, 868 insertions(+) diff --git a/Frameworks-or-Libraries/React.md b/Frameworks-or-Libraries/React.md index e69de29..742662f 100644 --- a/Frameworks-or-Libraries/React.md +++ b/Frameworks-or-Libraries/React.md @@ -0,0 +1,868 @@ +# React Cheatsheet + +Welome to C4GT's React Cheetsheet here you will find everything to start with React. + +**Check prereq** + +[Javascript](https://github.com/Code4GovTech/cheatsheets/blob/main/Languages/Javascript.md) + + +# Table of Contents + + + * [Basic React commands](#Basic-React-commands) + * [JSX](#JSX) + * [Injection JS into HTML](#Injection-JS-into-HTML) + * [Element declaration](#Element-declaration) + * [Function injection](#Function-injection) + * [Attributes](#Attributes) + * [Fragments](#Fragments) + * [References](#References) + * [Components](#Components) + * [Function component](#Function-component) + * [Class component](#Class-component) + * [Events](#Events) + * [Conditional element](#Conditional-element) + * [List of elements](#List-of-elements) + * [Content projection](#Content-projection) + * [Higher order component](#Higher-order-component) + * [Routing](#Routing) + * [Nested routing](#Nested-routing) + * [Routing with parameters](#Routing-with-parameters) + * [Authentication](#Authentication) + * [State and life cycle](#State-and-life-cycle) + * [State](#State) + * [Life cycle](#Life-cycle) + * [Forms](#Forms) + * [Http requests](#Http-requests) + * [Tests](#Tests) + * [Interaction](#Interaction) + * [Mocking http](#Mocking-http) + * [Mocking components](#Mocking-components) + * [Context](#Context) + * [Hooks](#Hooks) + * [Basic hooks](#Basic-hooks) + * [Other hooks](#Other-hooks) + * [Custom hook](#Custom-hook) + * [TypeScript in React](#TypeScript-in-React) + * [Add to project commands](#Add-to-project-commands) + * [Add type for custom DOM element](#Add-type-for-custom-DOM-element) + * [Interview questions](#Interview-questions) + + + + Basic React commands +================= + +| 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 +================= + +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 + +```jsx + const value = 'Hello world'; + return (
{value}
); +``` +'Hello world' will be injected and displayed inside `
` element + +## Element declaration + +```jsx + const value = 'Hello World'; + const element = {value}
; + return (element); +``` +We can assign specific DOM fragments to a particular variable (element above) and then (re)use it everywhere. + +## Function injection + +```jsx + function addNumbers(x1, x2) { + return x1 + x2; + } + const element = {addNumbers(2, 5)} +``` +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 +```jsx +  const avatarUrl = "img/picture.jpg" +  const element = ; +``` +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: +```jsx + + val1 + val2 + +``` + +or + +```jsx +<> + val1 + val2 + + +``` + +## References +We can refer to html element from JS + +1. Declare a reference +```js +this.element = React.createRef(); +``` + +2. Assign a reference to element +```jsx + +``` + +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](https://github.com/delprzemo/react-cheatsheet#other-hooks "other-hooks") ) + +Components +================= + +"React lets you define components as classes or functions. Components defined as classes currently provide more features" + +## Function component + +Sample component: +```js +function App() { +  return 
Hello World
; +} +export default App; +``` + +Sample component with parameters: + +```js +function Welcome(props) { +    return 

Hello, {props.name}

; +} +``` +```jsx + +``` + +## Class component + +Sample component: +```js +class App extends React.Component  { +  render() { +    return 
Hello World
; +  } +} +export default App; +``` + +Sample component with the parameters: + +```js +class Welcome extends React.Component  { +  render() { +    return 
Hello {this.props.name}
; +  } +} +export default App; +``` +```jsx + +``` + +## Events + +Sample `onClick` event in an element: +```jsx + Click me  +``` + +onClick function: +```jsx +onClick(e) { + e.preventDefault(); + // some logic here +} + +``` + +**Access to "this" inside event:** + +There are a few ways to achieve that: + +1. bind this +```js +this.onClick = this.onClick.bind(this); +``` + +2. 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` +```js +onClick = (e) => { +    e.preventDefault(); +    console.log(this); +} +``` + +or + +```jsx +  this.onClick(e)}> Click me +``` + +**Child event** + +We can call a function in parent component from the child component. + +Child component (somewhere in code): +```js +this.props.onChange(val1, val2,...) +``` + +Parent component: +```jsx + +``` + +```js +function hasChanged(val1, val2,...) { + // some logic here +} +``` + +## Conditional element + +Show element depending on the implemented condition + +**Option 1:** +```js +function SomeElement(props) { + const show = props.isShowed; + if(show) { + return 
Here is element
; + }          +} +``` +then: +```jsx + +``` + +**Option 2:** +```js +let element;       +if(this.state.isShown) { + element  = 
Here is element
; +}  +``` + +and then use the element variable in jsx + +**Option 3:** +```jsx +{this.state.isShow  ? 
Here is element
 : 'No element'} +``` + +**Option 4:** +```jsx +{this.state.isShow &&
Here is element
} +``` + +## List of elements + +The recommended way to show a list of the same components is to use the "map" function. Example: +```js +const numbers = [1, 2, 3, 4, 5]; +const listItems = numbers.map((numer, index) => +   +    {number} +   +); + +``` +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: +```jsx +

Hello world

+``` + +Child (MyElement) component: +```jsx +
+ {this.props.children} +
+``` + +`

Hello world

` will be injected to place where `{this.props.children}` has been used, so MyElement will look like: + +```jsx +
+

Hello world

+
+``` + +## Higher order component +Create a parameterized component in order to reuse it in different ways. + +Example: +```jsx +const myHoc = settings => WrappedComponent => { +    return class DecoratingComponent extends React.Component { +        render() { +            return () +        } +    } +} +``` + +Usage: +```jsx +const MyWrappedComponent = myHoc('test')(SomeComponent); + +``` +`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: + +```jsx + + + + + + + + +``` + +Link changing current url: + +```jsx +List +``` + +Tip: Route and Link need to be in same Router element + +## Nested routing + +Parent: +```jsx + +``` + +SomeComponent: +```js +function  SomeComponent({ match }) { +    return ( +         +             +                 +             +         +    ) +} +``` + +## Routing with parameters + +```jsx + +``` + +and then in SomeComponent we have access to: + +```jsx +{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: + +```jsx +function PrivateRoute({ component: Component, ...rest }) { +    return ( +         (_isAuthentictedLogic_) ? +            () : +            ( +            )} +        /> +    ); +} +``` + +Then instead of Route use PrivateRoute + +```jsx + +``` + + +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: +```js +constructor() { + this.state = { userId: 2, userName: "Jannice"}; +} +``` + +Using state: +```jsx +
{this.state.userName}
+``` + +Updating state: +```js +this.setState({ userId: 3, userName: "Tom"}); +``` +After setState component will be re-rendered + +## Life cycle + +| 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: +```jsx +componentDidMount() { + console.log("componentDidMount") + // some logic here +} + +componentWillUnmount() { + console.log("componentWillUnmount") + // some logic here +} +``` + +Forms +================= + +Sample form: + +```js +onValueChange  = (event) => { +    this.setState({ value:  event.target.value  }); +} +``` +```js +onSubmit = (e) => { + e.preventDefault(); + // Submit logic +} + +``` +```jsx + +     +     +     + +``` + +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: +```js +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: +```js +axios.post('/user', { +    firstName: 'Fred', + id: 2 +}).then(function (response) { + //some logic here +}) +.catch(function (error) { + //some logic here +}); +``` + +Example with async call: +```js +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: + +```jsx +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(, container); +  }); +  expect(container.textContent).toBe("Some text inside"); +}); + +``` + +## Interaction + +Click on element: +```js +import { fireEvent } from '@testing-library/react' +``` +```js +fireEvent.click(container.querySelector('.some-class)); +``` + +Change value in input: +```js +fireEvent.change(container.querySelector('.some-class)), { +    target: { value: "12345" } +}); +``` + +Check if element contains class +```js +expect(someEl.classList.contains('disabled')).toBe(false); +``` + +## Mocking http + +`npm install axios-mock-adapter --save-dev` + +Example: +```js +var axios = require('axios'); +var MockAdapter = require('axios-mock-adapter'); +var mock = new MockAdapter(axios); + +``` +```js +mock.onGet('/users').reply(200, { +  users: [ +    { id: 1, name: 'John Smith' } +  ] +}); +``` + +With specific parameter +```js +mock.onGet('/users', { params: { searchText: 'John' } }).reply() +``` + +## Mocking components +Example: +```js +jest.mock("./SomeComponent", () => { +  return function DummyComponent(props) { +    return ( +       +        here is square +       +    ); +  }; +}); + +``` + +Context +================= + +Context is a "bag" for some data common for node of components. + +Declare context: +```js +import React from 'react'; +export const ColorContext = React.createContext('red'); +``` +'red' is default value + +Create context and distribute it to child component: +```jsx +const { Provider } = ColorContext; +return ( +     +     +     +); +``` + +Use it in child component: +```js +const { Consumer } = ColorContext; +return ( + + {value => 
{value}
} +
+) +``` + +Use it in child component outside render function: +```js +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 +```js +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: +```js +useEffect(() => { +    document.title = `Clicked ${count}`; +}); +``` + +In order to act as componentWillUnmount: +```js +useEffect(() => { +    return () => {/*unsubscribe*/}; +}); +``` + + +**useContext hook** + +Hooks for context implementation. See [Context](https://github.com/delprzemo/react-cheatsheet#context "context") + +Parent: +```jsx +const CounterContext = React.createContext(counter); + +function App() { + return ( + + + + ); +} +``` + +Child: +```jsx +const counter = useContext(CounterContext); +``` + +## Other hooks + +| 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 hook +Custom hooks can be created. +Sample implementation: +```jsx +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 + +```ts +declare namespace JSX { +    interface IntrinsicElements {foo: any} +} +; // ok +; // 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](https://github.com/delprzemo/react-cheatsheet#content-projection "content-projection") + +**Q: Describe useEffect hook** + +A: UseEffect can replace componentDidMount, componentDidUpdate, componentWillUnmount and other life cycle component events. +See [Basic hooks](https://github.com/delprzemo/react-cheatsheet#basic-hooks "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: +```jsx +const myHoc = settings => WrappedComponent => { + return class DecoratingComponent extends React.Component { + render() { + return (
) + } + } +} +``` + +usage: +```jsx +const MyWrappedComponent = myHoc('test')(SomeComponent); + +``` + +**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](https://github.com/delprzemo/react-cheatsheet#JSX "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. \ No newline at end of file