Coder Social home page Coder Social logo

sanjar-notes / react Goto Github PK

View Code? Open in Web Editor NEW
1.0 1.0 1.0 18.86 MB

My understanding React web, native

Home Page: https://sanjar-notes.github.io/react/

front-end functional-components react react-js web hooks react-native deep-dive patterns low-level-design

react's Introduction

React.js

Live link

Why

My needs:

  1. Break down UIs into small functions
  2. Make my own "HTML components"
  3. Don't get bogged down writing glue code
  4. Use the latest JS syntax without problems

React provides:

  1. A sane way to build apps - specify the frames, without worrying about the transition code.
  2. Componentization - break down the UI into small reusable (and manageable) parts
  3. Simple DSL - it's like HTML except {js_expression_here} is used for including JS logic.
  4. Modules - JS, CSS files can be imported seamlessly
  5. Simple and stable app constructs
  6. Community support + docs + dev tools (the popularity!)

How

  • React uses a heuristics-based algorithm to "figure out" transitions between frames automatically.
  • It provides simple and stable app constructs (functions that you can import and use), so app development is practically declarative.

What

React is a declarative way to build user interfaces.

React is a library to create and reuse your own HTML tags.

โ€” Me when I started using React

Usage


These are notes (mental models) I made while doing this Udemy course(released 2020).

I have tried to compress and classify information into manageable chunks.

react's People

Contributors

sanjar-162 avatar sanjarcode avatar

Stargazers

 avatar

Watchers

 avatar

Forkers

akshitlakhera

react's Issues

How does React core optimization work

I have finally undertood how React optimization works.
There are two key concepts here:

  1. Batching DOM operations is a key optimization strategy. This was true even in 1995. And still is. Library/ framework agnostic.
  2. Reflow and repaint minimisation is at the heart of UI optimization. Virtual DOM is used to minimise reflow (which minimises repaints) and page inflation overhead (done on fresh page - a large constant).

There may be some more nunaces here. But this covers the gist of it.

I was fed up superficial answers and explanations, so I tried to recreate the VDOM from the core idea of React - efficiently do dumb page reload. This replaces hard "smartness" in DOM changes (in vanilla JS) by declarative code.

And so the tagline for React is simple, albeit useless for a beginner.

React - a way to write Uls declaratively.

๐Ÿ˜‚๐Ÿ˜ƒ

So, React core replaces human smartness (and so effort) by a deterministic algorithm, with certain heuristics of course.

If an Al could be added to React core, would it improve it even more?

I think so. Would it matter? No for significant part of web development. Yes for mobile app development.

The best part - Al or not, declarativeness is preserved.

In short React optimization works on two things:

  1. Graphics - repaints (dependent on reflows).
  2. Pure computation - page inflation, some parts of reflows.

An analogy (speed):

  • JS -> CPU
  • DOM -> cache
  • Reflow op - RAM
  • Repaint (display) - disk

~3 orders of magnitude difference.
Studying hardware in college is atleast of some use ๐Ÿ˜‚.

Trick - render component with 'hidden' attribute, copy innerHTML

For libraries that are not React first, or don't have much support for custom UIs in their parts (you ApexChart Donut Label ;))

Today, I did a very cunning hack ๐Ÿ˜‚ - rendered a component (with hidden attribute) and copied over it's HTML into Apex node (since it expects HTML), using a useEffect

Worked without issues, events and everything.

No more problems with normal (non React/Vue) JS libs from now on, ig. Will check perf.

Change file extension .js to .jsx if file contains JSX code - for Vite

bro kind of works for changing all file from .js to .jsx but not efficient because leaving few things need to optimise containsJSX
โ€” @Briyani-monster (Ashish)

const fs = require("fs");
const path = require("path");
const babel = require("@babel/core");

// Define the directory where your JavaScript files are located
const sourceDir = "./src";

// Ensure the source directory exists
if (!fs.existsSync(sourceDir)) {
  console.error(`Source directory "${sourceDir}" does not exist.`);
  process.exit(1);
}

function containsJSX(code) {
  
  return code.includes("import PropTypes");
}

// Function to convert a JavaScript file to JSX
function convertFileToJSX(filePath) {
  const code = fs.readFileSync(filePath, "utf-8");

  if (containsJSX(code)) {
    // Replace .js with .jsx in the filePath
    const jsxFilePath = path.join(
      path.dirname(filePath),
      path.basename(filePath).replace(".js", ".jsx")
    );

    fs.renameSync(filePath, jsxFilePath);
    console.log(`Renamed and converted: ${filePath} => ${jsxFilePath}`);
  }
}

// Recursively read and convert JavaScript files in the source directory
function convertFilesInDirectory(directory) {
  const files = fs.readdirSync(directory);

  for (const file of files) {
    const filePath = path.join(directory, file);
    if (fs.statSync(filePath).isDirectory()) {
      convertFilesInDirectory(filePath);
    } else if (filePath.endsWith(".js")) {
      convertFileToJSX(filePath);
    }
  }
}

// Start the conversion process
convertFilesInDirectory(sourceDir);

Purpose of keys in React

I'll not get into what's the purpose of keys, from a first principles viewpoint.

Known purpose:

  1. List of same node type - solve prepend inefficiency problem, or similar positional inefficiency.
  2. Force unmount (and maybe subsequent mount) by passing key prop.

Revisit ReactRouter v6

I learnt v5, but skipped v6. Revisit it. Especially query params parts, examples:

const { useNavigate, createSearchParams } from 'react-router-dom';


const navigate = useNavigate();

const goToOrbit = () => {
  navigate({
    pathname: ROUTES.energy.dysonSphere,
    search: createSearchParams({
      [MY_FOCUS_SLIDERS_SEARCH_PARAMS.energy.dysonSphere.orbit]: orbitId,
    }).toString(),
  });
};
const { useSearchParams } from 'react-router-dom';


const [searchParams, setSearchParams] = useSearchParams();

[...searchParams]; // get array from iterator

const restartOrbit = (id) => {
  searchParams.delete("status");
  searchParams.append(MY_FOCUS_SLIDERS_SEARCH_PARAMS.energy.dysonSphere.orbit, id);
  searchParams.append("force", true);

  setSearchParams(searchParams);
};
const { Link, createSearchParams } from 'react-router-dom';

// same as useNavigate()'s argument
const linkTo = {
  pathname: ROUTES.energy.dysonSphere,
  search: createSearchParams({
    [MY_FOCUS_SLIDERS_SEARCH_PARAMS.energy.dysonSphere.orbit]: orbitId,
  }).toString(),
  // hash, and other properties can be added
};

<Link to={linkTo} />

Does useEffect cleanup respect React's batching flow (i.e. does it run synchronously)?

Situation

A React app just has one component. There are two instances of it, that are run (mounted) in order (controlled by React Router based on query param, say).

Expected (as per my current knowledge, and for sane DX ๐Ÿ˜…)

1st mounts
1st cleanup runs
1st unmounts

2nd mounts
2nd cleanup runs
2nd unmounts

The useEffect code.

useEffect(() => {
  console.log("Mounted", currentPageIdx);

  return () => {
    console.log("Cleanup started for", currentPageIdx);

    // long synchronous operation
    for (let i = 0; i < +1e10; i += 1) {
      const j = 0;
    }

    console.log("Cleanup started for", currentPageIdx);
  };
}, [currentPageIdx]);

To investigate/verify

  1. Is the order stated above, correct?
    1. If not, is it possible that the second instance gets mounted, and the cleanup for the first runs after it.
    2. More fundamentally - does the cleanup function run after component has been cleared from DOM, or after component is cleared from the DOM. This question is a general one, not immediately specific to this situation.
  2. Does React guarantee such, synchronous behavior
  3. What happens if the cleanup does some async task?
    1. Does the async part run outside the React sync/batch flow
    2. If yes, how to make React wait to run other code, until the async task is done.

Why this trivial question

I was debugging at work, when I apparently saw the cleanup for the first being run after the second one had mounted.

Useful React supporting functions and libraries

Routing

  • React Router - for routing to components

Network requests

  • React Query - for optimised network requests

State management

  • Context API (not a library but useful)
  • Redux - becoming potentially obsolete but still useful

Testing

  • React Testing Library
  • Cypress

Animations

TBD

SSR

  • Next.js

Project setup

  • create-react-app
  • Vite.js

React server components (primer?)

https://youtu.be/Fctw7WjmxpU (4 hr exploration with Dan Abramov)

A simple way to think about RSCs:

  1. Assumption - The SPA assumption doesn't hold true in many cases - of sending the whole code to the client.
  2. Efficiency - Current pure SPA architecture neglects the efficiency issues with client side massaging of data, and also network performance

Can't get latest Redux store entity after dispatch, inside callback.

Situation + Problem

The following code doesn't work.

const dispatch = useDispatch();

const paymentForm = useSelector(myPaymentFormSelector);

const submitHandler = () => {
  dispatch(someLastThing()); // which will change "paymentFormSelector" entity in store

  paymentForm; // not the latest value, since it's pointing to a closured value

  removeMyFormFromView();
}

Observations:

  • Technically, this is a JS detail, not something Redux specific.
  • It's a React problem, more than a Redux problem - rules of hook. can't use them inside a callback (since hooks can be called in components, and that too at the first level).

Redux:

  • What Redux/RTK lacks is a way to add the callback logic that uses latest store, after dispatch.

Workaround ('solution')

Use useEffect, with a boolean state (useState), and move the logic after 'dispatch' in the useEffect.

Code:

const dispatch = useDispatch();
const [done, setDone] = useState(false);

const paymentForm = useSelector(myPaymentFormSelector);

const submitHandler = () => {
    dispatch(someLastThing());
   // which will change "paymentFormSelector" entity in store
}

useEffect(() => {
  if(done) {
    paymentForm; // OK

    removeMyFormFromView();
  }
}, [done]);

useLayoutEffect

A hook to run code just before React paints the DOM. Common use case if determining layout parameters for stuff like scroll preservation etc.

Mental model
component code runs --> React vDOM calculated -->                           React paints DOM --> useEffect runs
component code runs --> React vDOM calculated -->  useLayoutEffect runs --> React paints DOM --> useEffect runs

One base class component, others usual functional

Hi guys.

Is it possible to structure a React project (say v2) such that tooltipText is a global prop picked up on any component? ๐Ÿฆ„๐ŸŒˆ

Like native HTML title attribute. (the naive tooltip box is not customizable, FYI)

In short - extending (OOP) the "BaseReactComponent" if there's something like that?

Approaches:

  1. attribute selector shows tooltip, But works with native HTML tags only.
  • Solution
      /* CSS - Base styling for tooltips */
      [data-tooltip] {
        position: relative;
        cursor: pointer;
      }
    
      [data-tooltip]::before {
        content: attr(data-tooltip);
        position: absolute;
        bottom: 100%; /* Position above the element */
        left: 50%;
        transform: translateX(-50%);
        padding: 0.5em 1em;
        background-color: rgba(0, 0, 0, 0.8);
        color: #fff;
        border-radius: 4px;
        font-size: 12px;
        white-space: nowrap;
        opacity: 0;
        visibility: hidden;
        transition: opacity 0.2s, visibility 0.2s;
      }
    
      /* Show the tooltip on hover */
      [data-tooltip]:hover::before {
        opacity: 1;
        visibility: visible;
      }
    JSX
    <span data-tooltip="Tooltip text" >Hello, world</span>
    -- @amolikvivian
  1. Wrapper that has a span (that does point 1). Con: only tooltips will be visible.
  • Solution
    /* CSS - same as .1 */
     export default function TooltipWrapper({ children, tooltipText }) {
        <span data-tooltip={tooltipText}>{children}</span>;
     }
     
     <TooltipWrapper tooltipText="wefbwfw">
         <MyComponent />
    <TooltipWrapper />    
  1. Original - detect prop passed to custom component. Weren't able to do.

// after some time...

Ok guys ~1 hr on this I've spent.

Lesson learnt: if you want complete control, make 'One' class component, then use it in all functional components.

Extensibility ftw, perf idk

Props change does not unmount/remount component - persistent knowledge hole.

What I understand and am confident about:

  1. State is ephemeral, independent for each component. Ancestory does not matter.
  2. State but cannot be reset. re-set is possible, but reset is not possible.
  3. Prop change does not remount a component. A component unmounts only if it's absent in the next frame.
  4. State gets destroyed only on unmount.
  5. Bonus - key prop (changing of) can be used to cause an unmount.
  6. Components are re-run, all the way to the leaf nodes. React.memo can be used to prevent re-run.

Ternary and short-circuit rendering are different in React (JSX)

  • Ternary - instances for both cases are preserved, or this is what effectively happens
  • Short-circuit - instances are destroyed and re-created

Simple example:
This (ternary)

{tired ? <Rest /> : <Play />}

is not equivalent to (short-circuiting)

{tired && <Rest />}
{!tired && <Play />}

Realistic example:

import { useState } from "react";

export default function MyApp() {
  const [show, setShow] = useState(true);
  return (
    <div>
      <h1>Counters that update separately</h1>
      <button onClick={() => setShow((_) => !_)}>onClick</button>
      {show ? <MyButton title="first" /> : <MyButton title="second" />}
      {show && <MyButton title="first" />}
      {!show && <MyButton title="second" />}
    </div>
  );
}

function MyButton({ title }) {
  const [count, setCount] = useState(0);

  function handleClick() {
    setCount(count + 1);
  }

  return (
    <button onClick={handleClick}>
      Clicked {count} {title} times
    </button>
  );
}

React state update, re-rerun, re-render

Seems trivial, but I didn't know that React doesn't re-render if one one sets the same state.

Here's a rough sketch (mostly guesswork, may be wrong):

// Component(props, state) => [Child1, Child2, Child3]
// 0. Why would someone have a child -> it's a part that helps you.
  // 1. Root component (props = null), state = could be something.
      // State remains same: do nothing
      // state changes. Re - rerun: yes. Re - render children: if their props have changed
      // update state called by state did not change - (re-rerun - no, re-render children: no).
  // 2. Non-root component (props = nonNull, state = nonnull).
      // props change - (re-rerun, yes or decide using React.memo), (re-render children: only if child props have changed).
      // state change - (re-rerun, yes), (re-render children - only if child props have changed)
        // update state called by state did not change - (re-rerun - no, re-render children: no).
// 0. Someone can have a child just for the sake of having one.
  // 1. Root component (props = null), state = could be something.
      // State remains same: do nothing
      // state changes. Re - rerun: yes. Re - render children: YES always (as they could be independent)
      // update state called by state did not change - (re-rerun - no, re-render children: YES (as they could be independent)).
  // 2. Non-root component (props = nonNull, state = nonnull).
      // props change - (re-rerun, yes or decide using React.memo), (re-render children: only if child props have changed).
      // state change - (re-rerun, yes), (re-render children - only if child props have changed)
        // update state called by state did not change - (re-rerun - no, re-render children: no).

React books - for deep understanding (optional)

Books:

  1. Alex Banks and Eve Porcello - Learning React Modern Patterns for Developing React Apps-O'Reilly (2020)
  2. Robin Wieruch - The Road to React-Leanpub (2021)

Both discuss modern React (i.e. functional components).

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.