kurtzace / diary-2024

0 stars 0 forks source link

UI Study - React 18 #10

Open kurtzace opened 5 months ago

kurtzace commented 5 months ago

React 18

course1 And book React and React Native - Fifth Edition -Adam

And Book learning-react-2nd Edition - Alex Banks

Useful courses

Book

PluralSight and Udemy

Concurrent features:

  1. <Suspense fallback={<div>Loading...</div>}><div>UI...</div> </Suspense>, lifecycle with useTransition
  2. SuspenseList
  3. Hook useDefferedValue for stale UI

import { useTransition, useState } from 'react'; function App() { } const [isPending, startTransition] = useTransition(); const [someState, setSomeState] = useState(); const someEvent = (event) => { } startTransition (() => { }); setSomeState(event.target.value); return <SlowComponent value={someState} />;

Online course editors: CodeSandbox, StackBlitz, and Replit.

React frameworks include Next.js, Gatsby, and Remix

Vite generate: npm create vite@latest my-react-app -- --template react

Renderers: React DOM, React Native, React PDF, and React Unity.

useCallback and useMemo: These Hooks are used for performance optimization. useCallback memoizes a function, preventing it from being recreated on every render, while useMemo memoizes a value, recomputing it only when its dependencies change.

"const inputRef = React.useRef(null);"

nav and routes

export type SortOrder = "asc" | "desc";
function UsersContainer() {
  const [users, setUsers] = useState<string[]>([]);
  const [search] = useSearchParams();
  useEffect(() => {
    const order = search.get("order") as SortOrder;
    fetchUsers(order).then((users) => {
      setUsers(users);
    });
  }, [search]);
  return <Users users={users} />;
}

declare async routes

const router = createBrowserRouter([
  {
    path: "/",
    element: <UsersContainer />,
    errorElement: <p>Route not found</p>,
  },
  {
    path: "/users/:id",
    element: <UserContainer />,
    errorElement: <p>User not found</p>,
    loader: async ({ params }) => {
      const user = await fetchUser(Number(params.id));
      return { user };
    },
  },
]);
function App() {
  return <RouterProvider router={router} />;
}

then use loaded data

function UserContainer() {
  const params = useParams();
  const { user } = useLoaderData() as { user: User };
  return (
    <div>
      User ID: {params.id}
      <UserData user={user} />
    </div>
  );
}

children

"const routes: RouteObject = { path: "/one", element: , children: ["

lazy component

function App() {
  const [MyComponent, setMyComponent] = React.useState<() => React.ReactNode>(
    () => () => null
  );
  React.useEffect(() => {
    import("./MyComponent").then((module) => {
      setMyComponent(() => module.default);
    });
  }, []);
  return <MyComponent />;
}

or better use

const MyComponent = React.lazy(() => import("./MyComponent"));
function App() {
  return <MyComponent />;
}

Lazy components need to be rendered inside of a Suspense component.

Material UI React library

import Typography from "@mui/material/Typography"; import Container from "@mui/material/Container";

grid stack

<Grid container spacing={2} sx={{ backgroundColor: "#F3F6F9" }}>
      <Grid xs={12}>
        <Item sx={headerFooterStyle}>
          <Typography sx={mainStyle}>Header</Typography>

useLocation() to get the current pathname

MUI menu <FormControl> <InputLabel id="select-label">My Select</InputLabel> <Select..<MenuItem ..<Button variant="contained"/outlined


Compose function

const both = date => appendAMPM(civilianHours(date)); or const both = compose( civilianHours, appendAMPM); both(new Date());

const compose = (...fns) => arg => fns.reduce((composed, f) => f(composed), arg);

Long form of JSX React.createElement( "ul", { className: "ingredients" }, React.createElement("li", null, "2 lb salmon")


input pattern

instead of copying pasting value={title} onChange={event => setTitle(event.target.value)} then use it like <input {...colorProps}


Context

export const ColorContext = createContext();

render(
  <ColorContext.Provider value={{ colors }}><App />

retrieve it later using const { colors } = useContext(ColorContext); instead of <ColorContext.Consumer>{context => {

Context + Hook

imagine we have a ColorProvider

export default function ColorProvider ({ children }) {
  const [colors, setColors] = useState(colorData);

  const addColor = ( color) =>
    setColors([
      ...colors,
      {
        id: v4(),
       rating:0,
        color
      }
    ]);

  const rateColor = (id, rating) =>
    setColors(
      colors.map(color => (color.id === id ? { ...color, rating } : color))
    );

  const removeColor = id => setColors(colors.filter(color => color.id !== id));

  return (
    <ColorContext.Provider value={{ colors, addColor, removeColor, rateColor }}>
      {children}
    </ColorContext.Provider>
  );
};

we can have a hook const ColorContext = createContext(); export const useColors = () => useContext(ColorContext); wrapped under `

,`

later const { colors } = useColors(); or const { rateColor, removeColor } = useColors();

useLayoutEffect

useLayoutEffect is called at a specific moment in the render cycle. The series of events is as follows:

Render
useLayoutEffect is called
Browser paint: the time when the component’s elements are actually added to the DOM
useEffect is called
kurtzace commented 5 months ago

react test

React test utils

kurtzace commented 5 months ago

pkellner/pluralsight-using-hooks-in-react18 and the books

Sapling to view React component tree

useEffect(() => { return () => {} }, [])

Basic Hooks useState, useEffect, useContext Additional Hooks useReducer, useCallback, useMemo, useRef, uselmperativeHandle, useLayoutEffect, useDebugValue, useDeferredValue, useTransition, useld Library Hooks useSyncExternalStore, uselnsertionEffect

const [state, dispatch] = useReducer (reducer, initialArg, init); reducer: A function that takes in 2 parameters, state and action and returns a new state. initialArg: The starting value of state. init: A function that returns the starting state

const imgRef = useRef();
return (
<div className="container">
<img src="/images/Speaker-1124.jpg"
ref={imgRef}
style={{ filter: "grayscale (100%)" }} onMouseOver={() => {
}}
imgRef.current.style.filter = "grayscale (0%)";|
/>

In a controlled component, the from values are managed by React and not the DOM. They do not require us to use refs. They do not require us to write imperative code. const [title, setTitle] = useState("");

<input value={title} onChange={event => setTitle(event.target.value)}

or even better - make input hook

export const useInput = initialValue => {
  const [value, setValue] = useState(initialValue);
  return [
    { value, onChange: e => setValue(e.target.value) },
    () => setValue(initialValue)
  ];
};

// then

const [titleProps, resetTitle] = useInput("");

<input {...titleProps}

usecontext usage image

prop drilling image - Train from San Francisco to DC

vs useContext image - Flight from San Francisco to DC

export const ColorContext = createContext();
render( <ColorContext.Provider value={{ colors }}>     <App />

later somewhere in middle of app const { colors } = useContext(ColorContext);

old way was

<ColorContext.Consumer>
      {context => {

stateful providers

ColorProvider ({ children }) {
  const [colors, setColors] = useState(colorData);
  return (
    <ColorContext.Provider value={{ colors, setColors }}>
      {children}
    </ColorContext.Provider>

Instead of exposing the ColorContext instance, we can create a hook called useColors that returns the colors from context:

const ColorContext = createContext();
export const useColors = () => useContext(ColorContext);

// then things will be as simple as 

<ColorProvider>
    <App />
  </ColorProvider>

//later
const { colors } = useColors();

preferred way to useEffect

useEffect(() => {
  console.log(`saved phrase: "${phrase}"`);
}, [phrase]);

but cautions - phrase is not a deep dependency

instead of

 useEffect(() => {
    console.log(`saved phrase: "${phrase}"`);
  });

also remember to destroy, remove event listeners

useEffect(() => {
  newsFeed.subscribe(addPost);
  window.addEventListener("keydown", forceRender);
  return () => {
    newsFeed.unsubscribe(addPost);
    window.removeEventListener("keydown", forceRender);
  };
}, []);

another lifecycle

useLayoutEffect is called at a specific moment in the render cycle. The series of events is as follows:

Render

useLayoutEffect is called

Browser paint: the time when the component’s elements are actually added to the DOM

useEffect is called

example things inside useLayoutEffect

setWidth(window.innerWidth);
    setHeight(window.innerHeight);

remember computations and functions

words are calculated with every render? how about const words = useMemo(() => children.split(" "), [children]);

even memo pure components

const Cat = ({ name }) => {
  console.log(`rendering ${name}`);
  return <p>{name}</p>;
};
const PureCat = memo(Cat);

const RenderCatOnce = memo(Cat, () => true);
const AlwaysRenderCat = memo(Cat, (prevProps, nextProps) => false);

useCallback can be used like useMemo, but it memoizes functions instead of values. For example:

const memoizedCallback = useCallback(() => { //.. do something with a & b }, [a, b])

useCallback is to prevent a component from re-rendering unless its props have changed.

above both replaces shouldComponentUpdate

State Management

useReducer

const [checked, setChecked] = useState(false);

  function toggle() {
    setChecked(checked => !checked);
  }

  return (
    <>
      <input type="checkbox" value={checked} onChange={toggle} />

better is const [checked, toggle] = useReducer(checked => !checked, false);

const [number, setNumber] = useReducer(
    (number, newNumber) => number + newNumber,
    0
  );

some have habit of doing const [user, setUser] = useState(firstUser);

then setUser({ ...user, admin: true }); //imagine bug is there when developer forgets spread

or better is

const [user, setUser] = useReducer(
    (user, newDetails) => ({ ...user, ...newDetails }),
    firstUser
  );

then setUser becomes as simple as setUser({ admin: true });

AMUL Butter: Teach everyone to spread, they’ll spread for a day. Teach everyone to useReducer and they’ll spread for life.

redux

function counterReducer(state = { count: 0 }, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    default:
      return state;
  }
}
const store = createStore(counterReducer);
store.subscribe(() => console.log(store.getState()));
store.dispatch({ type: 'INCREMENT' });
store.dispatch({ type: 'DECREMENT' });

redux-thunk is a middleware that allows you to call action creator functions that return a function instead of an action object.

function fetchUserData() {
  return (dispatch) => {
    dispatch({ type: 'LOADING_USER_DATA' });
    fetch('/api/user')
      .then((response) => response.json())
      .then((data) => dispatch({ type: 'FETCH_USER_DATA_SUCCESS', payload: data }))
      .catch((error) => ....;
  };
}
const store = createStore(reducer, applyMiddleware(thunk));
store.dispatch(fetchUserData());

hooks

 const count = useSelector((state) => state.count);
  const dispatch = useDispatch();

mobx

for lighter weight / libraries

class Store {
  @observable count = 0;
  @action increment() {
    this.count += 1;
  }
  @action async fetchCountFromServer() {
    const response = await fetch('/count');
    const data = await response.json();
    this.count = data.count;
  }
}
const myStore = new Store();

//later

import { observer } from 'mobx-react';
import myStore from './myStore';
const Counter = observer(() => {
  return (
    <div>
      <div>Count: {myStore.count}</div>
kurtzace commented 4 months ago

State options

3rd party: redux, mobx, recoil

Remote: react query, swr, relay/Apollo

Webstore: local, session , index db

Local state

Lifted state

Derived : length of array

Refs : dom, uncontrolled components, non react libs , hold timer, track of component is mounted, store prev state value, undo ,redo

Url

kurtzace commented 2 months ago

Compliance

//@flow

type Props = { item: string };

function App(props: Props) { //... }

3. TypeScript

class/enum/types/interfaces/primitieves/tuple/ OOPS

## Testing

jest

describe("Math functions", () => { test("Multiplies by two", () => { expect(timesTwo(4)).toBe(8); });


simple react

const div = document.createElement("div"); ReactDOM.render(, div); expect(div.querySelector("svg")).toBeTruthy();


react testing library

import { toHaveAttribute } from "@testing-library/jest-dom"; expect.extend({ toHaveAttribute });

test("renders a star", () => { const div = document.createElement("div"); ReactDOM.render(, div); expect( div.querySelector("svg") ).toHaveAttribute("id", "hotdog"); });

//or better

import { render, fireEvent } from "@testing-library/react"; test("renders an h1", () => { const { getByText } = render(); const h1 = getByText(/Great Star/); expect(h1).toHaveTextContent("Great Star");

const { getByLabelText } = render(); const checkbox = getByLabelText(/not checked/i); fireEvent.click(checkbox); expect(checkbox.checked).toEqual(true);

});

or include all matchers

import * as matchers from "@testing-library/jest-dom/matchers"; expect.extend(matchers); afterEach(() => { cleanup(); });


reduce the getBy... with

<input ... data-testid="checkbox" // Add the data-testid= attribute />

getByTestId("checkbox");

Jest ships with Istanbul for code coverage

const { result } = renderHook(() => useCounter()); expect(result.current.count).toBe(0);


#### vite test 
"npm install -D vitest"

import { beforeAll, describe, expect, it, vi } from 'vitest'; import { getSteps } from './ios-health-kit'; describe('IOS Health Kit', () => { beforeAll(() => { vi.mock('./ios-health-kit', () => ({ getSteps: vi.fn().mockImplementation(() => 2000), })); }); it('should return steps', () => { expect(getSteps()).toBe(2000); expect(getSteps).toHaveBeenCalled(); }); });


Mock Service Worker for mocking server requests. It allows you to mock REST and GraphQL requests very flexibly. 

import { http, HttpResponse } from 'msw'; import { setupServer } from 'msw/node'; import { describe, it, expect, beforeAll, afterEach, afterAll } from 'vitest'; const server = setupServer( http.get('https://api.github.com/users', () => { return HttpResponse.json({ firstName: '.... }); }) ); describe('Mocked fetch', () => { beforeAll(() => server.listen()); afterEach(() => server.resetHandlers()); afterAll(() => server.close()); it('should returns test data', async () => { const response = await fetch('https://api.github.com/u

fake timers

describe('delayed execution', () => { beforeEach(() => { vi.useFakeTimers() }) afterEach(() => { vi.restoreAllMocks() }) it('should execute the function', () => { executeInMinute(mock) vi.runAllTimers() expect(mock).toHaveBeenCalledTimes(1) }) it('should not execute the function', () => { executeInMinute(mock) vi.advanceTimersByTime(2) expect(mock).not.toHaveBeenCalled() })


 spyable fake functions

example

const selector = (onSelect: (value: string) => void) => { onSelect('1'); onSelect('2'); onSelect('3'); };

test('selector', () => { const onSelect = vi.fn(); selector(onSelect); expect(onSelect).toBeCalledTimes(3); expect(onSelect).toHaveBeenLastCalledWith('3'); });

const spy = vi.spyOn(cart, 'getProducts');


#### React test utils
- showRender
- renderIntoDocument
`
- findRendered DOMComponentWithTag
- scryRenderedDOMComponents With Tag
- Simulate
Clicks
Keypresses
Etc.`

## Playwright - Automated Software testing
[Automated Software Testing with Playwright](https://cisco.udemy.com/course/automated-software-testing-with-playwright/)

BDD cucumber

Page object model

by Microsoft

headless vs headful

python, java, net, javascript*

Fast

no need to wait

------

.prettierrc 
`{ semi false, singleQuote true}`

`npm i @playwright/test`

`npx playwright install` installs chromium, webkit, firefox, ffmpeg

import {test, expect} from @playwright/test test('...', async ({page})=> { await page.goto("https://...") const pt = await page.locator('h1') await expect(pt).toContainText('.....') })


`npx playwright test` or `npx playwright test --headed` or `npx playwright test --browser=firefox` or `...--browser=all`
or `.... tests/example.spec.ts`
-----

page.click('#btnId') page.click('text=Sign In') const err= await page.locator('.myClassName') expect(err).toContainText('...') page.click('//button') page.fill('#username', '........') //to type expect(page).toHaveUrl('https://...'). to HaveTitle

expect(elem).toHaveCount(1)

----

to skip `test.skip`, test.only

test.describe('',()=> {

}


`npx playright test --grep @myTag` if `test('asse.. @myTag'`. -grep-invert to ignore

playright.config.ts

import {PlaywrightTestConfig} from @.../test

config config:playwrightTestConfig = { timeout: retries: use { headless: true viewport:{width:1280,} actionTimeout ignoreHttpsErrors: video: 'off' screenshot: off' projects:[{name: uses:{browserName:'webkit'}}] } ...test --config=```

--reporter=html/junit/lline

npx playwright show-report

await page.screenshot({path:'screen.png', fullPage:true})

const elem = await page.$('h1')
await elem.screnshot({path:})

beforeEach, afterAll

export async function loadHomepage(page) {await page.togo('')}

kurtzace commented 1 week ago

React Fiber in 2017. Fiber was a rewrite of React’s rendering algorithm that was sort of magical in its execution. It was a full rewrite of React’s internals that changed barely anything about the public API

Good Javascript techniques

The compose function is a higher-order function. It takes functions as arguments and returns a single value:

const compose = (...fns) => arg =>
  fns.reduce((composed, f) => f(composed), arg);

converts const both = date => appendAMPM(civilianHours(date)); to

const both = compose(
  civilianHours,
  appendAMPM
);

both(new Date());

const dan = {
  type: "person",
  data: {
    gender: "male",
    info: {
      id: 22,
      fullname: {
        first: "Dan",
        last: "Deacon"
      }
    }
  }
};

deepPick("type", dan); // "person"
deepPick("data.info.fullname.first", dan); // "Dan"

const deepPick = (fields, object = {}) => {
  const [first, ...remaining] = fields.split(".");
  return remaining.length
    ? deepPick(remaining.join("."), object[first])
    : object[first];
};

event.preventDefault() , event.stopPropagation()

reduce

const max = ages.reduce((max, value) => (value > max ? value : max), 0);

or

when we want to add hash to array

const colors = [
  {
    id: "wfsfs",
    title: "myTitle",
    rating: 4
  },.....]

const hashColors = colors.reduce((hash, { id, title, rating }) => {
  hash[id] = { title, rating };
  return hash;
}, {});

will give {"wfsfs": {title, rating}}

Array.reduceRight end to begin

React old vs new

  1. create elem
    React.createElement(
    "ul",
    { className: "ingredients" },
    React.createElement("li", null, "2 lb salmon"),

or create class

const IngredientsList = React.createClass({
  displayName: "IngredientsList",
  render() {
    return React.createElement(

or classbased

class IngredientsList extends React.Component {
  render() {
    return React.createElement(

to be replaced by

ReactDOM.render(
  <Menu recipes={data} title="Delicious Recipes" />,
  document.getElementById("root")
);

and

function Menu({ title, recipes }) {
  return (
    <article>
      <header>
        <h1>{title}</h1>

and newer way is Render is now become createRoot in react 18

see

typical way to build

npm install --save-dev webpack webpack-cli @babel/preset-env @babel/preset-react

.babelrc:

{
  "presets": ["@babel/preset-env", "@babel/preset-react"]
}

simplest // ./webpack.config.js

var path = require("path");

module.exports = {
  entry: "./src/index.js",
  output: {
    path: path.join(__dirname, "dist", "assets"),
    filename: "bundle.js"
  },
 module: {
    rules: [{ test: /\.js$/, exclude: /node_modules/, loader: "babel-loader" }]
  },
devtool: "#source-map" // Add this option for source mapping
};

instead of all of above

npm install -g create-react-app

React 18 new features

  1. Auto batching
function handleClick() { setIsFetching(false); setError(null); setFormStatus('Success'); }

to force a refresh to specific state

import { flushSync } from "react-dom";
function handleClickWithFlush() {
   // will force a render
   flushSync(() => {
     setCount((c) => c + 1);
   });
   // will cause another render
   setIsEven((count + 1) % 2 === 0);
 }
  1. Transition urgent and non-urgent updates
// Urgent: Show what was typed 
setInputValue(input); 
//Mark any state updates inside as transitions 
startTransitions (() => { // Transition: Show the results 
setSearchQuery(input); }); 
  1. Suspense loading spinner, before sending HTML for the placeholder
const specialPromiseResource = getSpecialProgisetofetchlteas(); 
return ( <Suspense fallback={<div>Loading Itens</div>)>
                 <FoodList resource={specialPromiseResource} /> 
</Suspense> 

instead of

{loading ? (
       <p>Loading please wait...</p>
     ) : (
       <ListUniversities list={data} />
     )}

after image

image

  1. StrictMode React will be able to instantly mount a previous screen in the future thanks to the reusable state.

also see Render is now become createRoot in react 18

see

  1. new hooks a. useId : like uuid b. useDeferredValue : debouncing

  2. New way to create

npm create vite@latest my-react-app -- --template react

kurtzace commented 1 week ago

Async

API calls

best to use in useEffect

fetch(`https://api.github.com/users/moonhighway`)
  .then(response => response.json())
  .then(console.log)

or

const response = await fetch(
      `https://api.github.com/users/${githubLogin}`
    );
    const userData = await response.json();

images

const formData = new FormData();
formData.append("username", "moontahoe");
formData.append("fullname", "Alex Banks");
forData.append("avatar", imgFile);

how about make a hook

export function useFetch(uri) {
  const [data, setData] = useState();
  const [error, setError] = useState();
  const [loading, setLoading] = useState(true);

...useEffect(() => { .....fetch

...
 return {
    loading,
    data,
    error
  };

waterfall vs parallel

waterFall

<Fetch
  uri={`https://api.github.com/users/${login}/repos`}
  renderSuccess={({ data }) => (
    <RepoMenu repositories={data} onSelect={onSelect} />
  )}
/>

vs parallel

  <>
      <SearchForm value={login} onSearch={setLogin} />
      <GitHubUser login={login} />
      <UserRepositories  login={login}  repo={repo}   onSelect={setRepo} />
      <RepositoryReadme login={login} repo={repo} />
    </>

Waiting for Values {login && <GitHubUser login={login} />}

GQL

GraphQL API

const query = `
query findRepos($login: String!) {
  user(login: $login) {
    login
    name
    location
    avatar_url: avatarUrl
    repositories(first: 100) {
      totalCount
      nodes {
        name
      }  } } }
`

image

import { GraphQLClient } from "graphql-request";

const client = new GraphQLClient(url, {headers ...)
client
  .request(query, { login: "moontahoe" })

virtual list

react-window and react-virtualized. Virtualized lists are so important that React Native even ships with one: the FlatList

import { FixedSizeList } from "react-window";
<FixedSizeList
      height={window.innerHeight}
      width={window.innerWidth - 20}
      itemCount={bigList.length}
      itemSize={50}
    >{renderRow}
    </FixedSizeList>

Error boundaries

export default class ErrorBoundary extends Component {
  state = { error: null };

  static getDerivedStateFromError(error) {
    return { error };
  }

  render() {
    const { error } = this.state;
    const { children, fallback } = this.props;

    if (error) return <fallback error={error} />;
    return children;
  }
}

function ErrorScreen({ error }) {....

<ErrorBoundary fallback={ErrorScreen}>
  <App />
</ErrorBoundary>;

Loading components lazy

const Main = React.lazy(() => import("./Main"));

then

<Suspense fallback={<ClimbingBoxLoader />}>
      <Main />
    </Suspense>

Using Axios

axios.get('http://example.com/data')
  .then(response => console.log(response.data))

interceptors

this.apiInstance = axios.create({
      baseURL: "https://api.github.com",
    });
    this.apiInstance.interceptors.request.use((config) => {
      console.log("Request:", '${config.method?.toUpperCase()} ${config.url}');
      return config;
    });
    this.apiInstance.interceptors.response.use(
      (response) => {

Using TanStack Query


const queryClient = new QueryClient();
ReactDOM.createRoot(document.getElementById("root")!).render(
  <QueryClientProvider client={queryClient}>

const userFetcher = (username: string) =>
  fetch("https://api.github.com/users/sakhnyuk")
  .then((response) => response.json());

 const {
    data: user,
    isPending,
    isError,
  } = useQuery({
    queryKey: ["githubUser"],
    queryFn: () => userFetcher("sakhnyuk"),
  });

// naive

import { useQuery } from 'react-query';
function UserProfile({ userId }) {
  const { data, error, isLoading } = useQuery(userId, fetchUser);

websocket

const socket = new WebSocket('ws://example.com');
socket.onopen = function(event) {
  console.log('Connection established');
};
kurtzace commented 1 week ago

Router

import { BrowserRouter as Router, Link } from "react-router-dom";

render(
  <Router>
    <App />
  </Router>,

App() {
  return (
    <div>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route
          path="/about"
          element={<About />}
        />
<Route
          path=":id"
          element={<ColorDetails />}
        />
<Redirect
          from="services"
          to="about/services"
        />
<Route path="*" element={<Whoops404 />} />

 <Link to="about">About</Link>

and inside Whoops404 let location = useLocation(); {location.pathname}

or how about

let element = useRoutes([
    { path: "/", element: <Home /> },
    {
      path: "about",
      element: <About />,
      children: [

Params

ColorDetails() { let params = useParams();

to go navigate from inside js let navigate = useNavigate(); navigate(/${id})}

const query = new URLSearchParams({ msg: "From Query" });

kurtzace commented 1 week ago

React server

React frameworks include Next.js, Gatsby, and Remix.

Why? Seo/static/

npm install isomorphic-fetch

and

ReactDOM.renderToString, ReactDOM.hydrate instead of ReactDOM.render.

example

app.get("/*", (req, res) => {
  const app = ReactDOMServer.renderToString(
    <Menu />
  );
});

const nodeExternals = require("webpack-node-externals");

or better Server Rendering with Next.js

Pets.getInitialProps = async function() {

Rehydration: Loading JavaScript views on the client to reuse the server-rendered HTML’s DOM tree and data.

Prerendering Running a client-side application at build time and capturing initial state as static HTML.

force-dynamic value. This parameter explicitly tells Next.js that we want to generate a new page for each request.

For Static: Gatsby

kurtzace commented 1 week ago

Beyond web

Expo now supports web development, allowing you to run your app on the web using React Native for Web. This means that you can develop apps that work on Android, iOS, and the web using a single code base. Additionally, the Tamagui UI kit

JS engines such as V8, SpiderMonkey, and others, React Native also contains a JS virtual machine.

React Native started using the new Hermes virtual machine, and from 0.64

Our entire application structure is packaged into a single file using the Metro bundler. It is also responsible for transpiling JSX code into JS. If we want to use TypeScript, Babel can support it. It

kurtzace commented 6 days ago

Code Snippets: https://kurtzace.github.io/react_18_unleash_future/

My Notes

Prezi Slides

React 18 New Features - Unleash the future React 18 Performance Practices React 18 Testing , Complaince, SSE