React Fundamental

dieutb
7 min readOct 6, 2021

--

JSX

JSX Convention

  • inside a scope, it requires Capital Name and can use dot notation, but not expression MyComp[“checkbox01”]. eg:
  • literal string. ex:
    color=”red” || color={‘red’}
    msg=”&lt;hello” || msg={’<hello’}
  • prop default to true. eg: <MyComponent a /> (this.props.a => true)
  • render return:
    + React DOM
    + Arrays React DOM
    + ReactDOM portals (aim to render element in a different position)
    + value of number, string, boolean
    + ex: render() {return [<li>a</li>, <li>b</li>]}
  • children could be any sort of data:
    + data (string/number/json/etc)
    + ReactDom
    + Functional Component
    + etc
  • Boolean, Null, and Undefined Are IGNORED in Render => not thing
  • Short return for condition
    {showHeader && <Header />}

Rendering elements:

  • React elements are plain objects and are cheap to create.
  • React DOM takes care of updating the DOM to match the React elements.
  • React Only Updates What’s Necessary: React DOM compares the element and its children to the previous one, and only applies the DOM updates necessary to bring the DOM to the desired state.
ReactDOM (virtual DOM) manages state changes and re-renders
  • We could have one or many “root DOM”, and everything inside “root DOM” will be managed by React DOM.
  • To render a React element into a root DOM node, pass both to ReactDOM.render

Components and Props

  • Components help split the UI into the independent part and make it reusable. Currently, ReactJS has two types of component
    1. Functional Component: just a JS function that receives a single “props” and returns React elements.
    eg: function Welcome(props) {return <h1>{props.greeting}</h1>}
    2.
    Class Component (ES6): a class extends from React.Component
  • All React components must act like pure functions with respect to their props. A component cannot update its own props unless they are arrays or objects.
  • The React.lazy (return a Promise/async) function lets you render a dynamic import as a regular component. Usually go with Suspense Component. <Suspense fallback={<div>Loading...</div>}>...</>
    + Not supported in some server rendering so, use loadble-component instead.
    + Only support export default.
  • “<Fragment>” component of React allows returning multiple elements. Short syntax: <>…</>. Fragment also need a "key" when inside “loop/map”
    eg: return (<> <td>CHILD A</td><td>CHILD B</td> </>)
  • label “for” attribute in HTML is represented by “htmlFor
  • props "key" (see list and key)
  • props "children": represent for the arbitrary content of the component.

ref

  • Only use when it’s really needed
  • need input a function ref={(el) => {…}} OR implemented by React.createRef()
  • only pass to children Component by React.forwardRef(props, ref)
  • ref updates happen before componentDidMount or componentDidUpdate
# option 1: declare a variable equal to React.createRef()
this.textInput = React.createRef();
<input
type="text"
ref={this.textInput} />
this.textInput.current.focus()#option 2: input a function
setTextInputRef(el) {
this.textInput = el
}
<input
type="text"
ref={this.setTextInputRef} />
<input
type="text"
ref={ el => this.textInput = el } />

Forwarding refs (React.forwardRef)

  • forward ref to children-component by using forwardRef.
  • the function input 2 parameters props and ref and output a ReactDom
# Function Component
const SampleButton = React.forwardRef((props, ref) => (
<button ref={ref} className="button">
{props.children}
</button>
));

const ref = React.createRef();
<SampleButton ref={ref}>Click me!</SampleButton>;
  • For class Component
# Class Component
const Counter = React.forwardRef((props, ref) => {
class Counter extends React.Component {
constructor(props) {
super(props)
this.state = {
count: 0
}
}
render() {
return (
<div>
Count: {this.state.count}
<button ref={ref} onClick={() => this.setState({count: this.state.count + 1})}>Incr</button>
</div>
)
}
}

return <Counter />
})

State and Life Cycle

  • State is called local or encapsulated.
  • it’s very important to free up resources taken by the components when they are destroyed. Hence, remove all event in componentWillUnMount()
  • Life circle:
    1. ReactDOM.render()
    2. constructor(props)
    3. render() => insert into the DOM
    4. componentDidMount()
    . setState() => render()
    .componentWillUnmount() when the component removed from the DOM
  • React may batch multiple setState() calls into a single update for performance.
  • setState would change state and may lead to re-render the component. This is an expensive operation, it would cause a performance issue if it is not an async process.
  • Because this.props and this.state update asynchronously, we should not rely on their values to calculate the next state. We can update with the second form setState (input a function).

HANDLING EVENT

  • Use “e.preventDefault()” to prevent default instead of "return false".
  • To prevent the event bind “this” to your function, you could:
    1. define the function with an arrow function
    2. binding “this” of class to that function.
// option 1.1:
handleClick = () => {
console.log('this is:', this);
}
// options 1.2:
<button onClick={() => this.handleClick()}>
// options 2.1:
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
// options 2.2:
constructor() {
...
this.handleClick = this.handleClick.bind(this)
}
<button onClick={this.handleClick}>Delete Row</button>

Conditional Rendering

List and Key

  • Keys help React identify which items have changed, are added, or are removed.
  • In React, when creating a list of React Elements, you have to give every element a “key”. It should be unique, static, and must set on the represented element.
  • Diffing algorithm of React checks mapping key and state change to decide which DOM element would be changed. If key value is not unique and static, it would lead to some wrong updates from React. Never use the random key, it would cause really bad performance because re-rendering all elements every time.
  • We can skip the key only when the list and items are static (they are not computed and do not change) and the list is never reordered or filtered.
  • key is a special attribute of React, it does not allow access.
const listItems = items.map((item, index) =>
<ListItem item={item} key={item.id} />
);
  • We could use curly braces inside the “map

FORM

  • specify “value” (!= null, undefined) in the “controlled component”, it only could change through React.
  • <textarea>, <select> uses a value attribute to show/selected instead of its content.
  • For multiple <select> add attributes “multiple=true”.
    eg: <select multiple={true} value={['B', 'C']}>
  • <input type="file"> its value is read-only, it is an uncontrolled element.
  • Tip: we could write a general reusable handleChangeEvent method for all elements.

Context:

  • allow passing a value to its children-component implicitly.
  • A component only can apply one context.
  • If it’s not specified the contextName inside a Component
    static contextType = ThemeContext;
    OR
    MyComponent.contextType = ThemeContext
    ,
    it would apply the context of the closest [Context].Provider .
  • Get the value inside the Component by “this.context
  • Apply it sparingly because it makes component reuse more difficult. Use passing the Component as props to easily call it.
    ex: const ThemeContext = React.createContext(‘light’);
    <ThemeContext.Provider value=”dark”>…</>

Context.Consumer

  • This lets you subscribe change to a context
<MyContext.Consumer>
{value => /* render something based on the context value */}
</MyContext.Consumer>

lifting state up

  • Move the state of children to the nearest suitable ancestor.
  • The ancestor would own the shared states is called “source of truth”.
  • The event-change-function is defined at parent component then pass it to children

ROUTER

Class Default Props

Integrating with other Library

  • usually along with ref

https://reactjs.org/docs/integrating-with-other-libraries.html

TOOL SUPPORT

# CLI tools 
Create React App (client side rendering)
Next.js (server side rendering + client side rendering - multi page)
Gatsby
# bundled tools Webpack, Rollup or Browserify: parse code JSX to JS, ES6 to ES5 then compress to mini files# analysis code: eslint-plugin-jsx-a11y
{
"extends": ["react-app", "plugin:jsx-a11y/recommended"],
"plugins": ["jsx-a11y"]
}
# test accessible HTML aXe, aXe-core and react-axe

References

Webpack code-splitting support:

  • prevent duplicated modules.
  • import dynamic lib module.

Uncontrolled Components (when we want the Dom El control value itself)

Formik (the easier form way for React)

https://robinpokorny.medium.com/index-as-a-key-is-an-anti-pattern-e0349aece318

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Operators/Object_initializer#Computed_property_names

--

--

dieutb
dieutb

Written by dieutb

passion in finding solutions and research some things relate to technical and helpful in life. Also strongly interest in foods, travel, and gentle music :)

No responses yet