1.0.9 • Published 2 months ago

react-rerenderers v1.0.9

Weekly downloads
-
License
MIT
Repository
github
Last release
2 months ago

🌈 React-Rerenderers.js 🌈

React-Rerenderers is a new state management library. This is a quite unusual and yet efficient usage of React.js' hooks which offers a way to escape from React's hells hell.

React-Rerenderers.js replaces useState() with much smaller hooks like useInstance(), useInstanceValue() , useInstanceValueSetter() and useRerenderer(). As a result, React application development is drastically simplified.

👺 Features 👺

🪐 The Design Goal of React-Rerenderers.js 🪐

  • Control when to rerender manually and precisely.
  • Offer a way to manage React.js states without other frameworks.
  • Centralize business logic as Model-View Controller.
  • Modularize not only components but also dialogs.

🌈 Table of Contents 🌈

TOC-BEGIN: <>

TOC-END: <> TOC-GENERATOR: <> ":r! cat README.md | pandoc --toc --wrap=none -s README.md --from=markdown --to=markdown | sed -n '1,/^ *$/p"

Eliminate State Lifting and Prop Drilling

React Development with the traditional useState()

Assume you are creating a simple application as follows:

Example No.0

import React from "react";

export const AppView = () => {
  const [counter, setCounter] = React.useState(0); // << See this
  return (
    <div id="main-frame">
      <div
        id="main-object"
        className={`square${counter}`}
        onClick={(e) => setCounter((counter) => (counter + 1) % 4)}
      >
        <div>{counter}</div>
      </div>
      <div id="main-message">Click the Square</div>
    </div>
  );
};

In this demo, every time you click on the square where its ID is main-object, its CSS class will be set to square0, square1, square2 and square3 respectively. As the CSS class goes, the square moves around the screen to top-left, top-right, bottom-right and bottom-left, respectively.

In React-Rerenderers, we implement the same logic in the following manner:

React Development With Rerenderers's Value Accessors

Example No.1

import * as Rerenderers from "./react-rerenderers";

export const AppView = () => {
  const counter = Rerenderers.useInstanceValue("counter"); // << See this
  const setCount = Rerenderers.useInstanceValueSetter("counter"); // << See this
  return (
    <div id="main-frame">
      <div
        id="main-object"
        className={`square${counter}`}
        onClick={() => setCount((count) => count + 1)}
      >
        <div>{counter}</div>
      </div>
      <div id="main-message">Click the Square</div>
    </div>
  );
};

In the example above, it uses useInstanceValue() hook and useInstanceValueSetter() hook. Note that they have some similarities with useState(). While useState() returns the current state value and its setter function, useInstanceValue() returns only the current state value and useInstanceValueSetter() returns only its setter.

You might notice that their functionalities are identical; while React-Rerenderers offers separated hook functions for each functionality of getting the current state and setting the new state, useState() offers both functionalities at one go.

This small difference gives some advantages which useState() cannot achieve.

Before we go inside the description of the advantages, let's review the necessity of lifting states of useState() hook.

Necessity of Lifting States with React Hooks

See the example below:

Example No.2

I moved the click handler to a remote location which is defined in a different file.

Note that with the traditional useState() hook, you have to Lifting Up the useState() hook and then you have to Drilling Properties as following:

import React from "react";
import { AppButton } from "./AppButton.js";
import { AppSquare } from "./AppSquare.js";

export const AppView = () => {
  const [counter, setCounter] = React.useState(0); // << See this
  return (
    <div id="main-frame">
      <AppSquare counter={counter} />
      <AppButton setCounter={setCounter} />
    </div>
  );
};
export function AppButton({ setCounter }) {
  return (
    <button
      id="main-message"
      onClick={() => setCounter((count) => (count + 1) % 4)}
    >
      Click Me
    </button>
  );
}
export function AppSquare({ counter }) {
  return (
    <div id="main-object" className={`square${counter}`}>
      <div>{counter}</div>
    </div>
  );
}

Even though it does not seem to cause serious issues, it does cause some serious issues when it comes to a larger project.

  • As the number of pages increases, it is usually getting more difficult to modularize your logic when you have to shift up or down those state functions or objects. It requires more complicated works and finally it is going to be impossible to achieve.
  • As a state is lifted up, the more components are likely to be rerendered when the hook is called. This causes slowing down the rerendering process.
  • Components with animation should usually not be rerendered. Unexpected rerendering causes components to stop their animation.

React-Rerenderers.js can eliminate these Lifting Up and Drilling Properties necessity.

How Rerenderers Eliminates the State Lifting

See the following example:

Example No.3

import { AppButton } from "./AppButton.js";
import { AppSquare } from "./AppSquare.js";

export const AppView = () => {
  // It is not necessary to call `useState()` in
  // the root of the virtual DOM tree.
  // const [counter, setCounter] = React.useState(0);
  return (
    <div id="main-frame">
      <AppSquare />
      <AppButton />
    </div>
  );
};
import * as Rerenderers from "./react-rerenderers";

export function AppSquare() {
  const counter = Rerenderers.useInstanceValue("counter"); // << See this
  return (
    <div id="main-object" className={`square${counter}`}>
      <div>{counter}</div>
    </div>
  );
}
import * as Rerenderers from "./react-rerenderers";

export function AppButton() {
  const setCount = Rerenderers.useInstanceValueSetter("counter"); // << See this
  return (
    <button id="main-message" onClick={() => setCount((count) => count + 1)}>
      Click Me
    </button>
  );
}

Note that useState() hook calling at the <AppView/> component is eliminated.

And you will see that this small difference triggers a drastic change of the component design.

Trigger Rerendering without Hooks

React-Rerenderers offers unique useRerenderers() hook. With useRerenderers() hook you actually don't have to call any hook when only thing you want to do is to update the state.

Actually, this is the biggest surprise which I have encountered during I was designing React-Rerenderers. I have never thought if I could implement it in such a way.

See the following example:

Example No.4

import * as Rerenderers from "./react-rerenderers";

/*
 * Please note that this variable is not
 * defined inside a React component nor a React hook.
 */
let counter = 0;

/*
 * Again, please note that this function is not
 * defined inside a React component nor a React hook.
 */
const handleClick = () => {
  counter = (counter + 1) % 4;
  /*
   * This rerenders the component which called the
   * useRenderer() hook with the argument "counter".
   * See below.
   */
  Rerenderers.fireRerenderers("counter");
};

export const AppView = () => {
  /*
   * This is acutually the only hook which you have
   * to call in this framework. In order to mark
   * which component to rerender when the model state is
   * modified, you have to call useRerenderer() hook.
   */
  Rerenderers.useRerenderer("counter");
  /*
   * Note that you can read and write the variable which
   * is defined outside the domain of React.
   * Also note that it can be achieved
   * without these React hells hell.
   */
  return (
    <div id="main-frame">
      <div id="main-object" className={`square${counter}`}>
        <div>{counter}</div>
      </div>
      <button id="main-message" onClick={handleClick}>
        Click Me
      </button>
    </div>
  );
};

This actually opens a door for more aggressive optimization.

Implement Model-View Controller

In the previous section, we have seen that states are actually able to be stored outside hooks/components. And we also have seen that, by using useRerenderers() hook, it is able to manually invoke the rebuilding process of React Virtual DOM Tree.

It seemed to me as a hint to the possibility to a further optimization. I realized it is also able to store states as JavaScript objects outside React hooks/components. I think, this could be an implementation of Model-View Controller in React.js.

Basic

See the following example:

Example No.4

At first, define a class which contains all states in the same application.

import { fireRerenderers } from "./react-rerenderers";
export class AppModel {
  __counter = 0;
  set counter(v) {
    this.__counter = v % 4;
    fireRerenderers(this, "counter");
  }
  get counter() {
    return this.__counter;
  }
}
/*
 * Create an instance of the class.
 */
export const model = new AppModel();

After defining the model class, associate the created instance to the React Virtual DOM Tree by InstanceProvider component.

import "./styles.css";
import { InstanceProvider } from "./react-rerenderers";
import { AppView } from "./AppView.js";
import { model } from "./AppModel.js";
import React from "react";

export default function App() {
  return (
    <InstanceProvider factory={() => model}>
      <AppView />
    </InstanceProvider>
  );
}

In AppView component, it is able to access to the instance by useInstance() hook.

import * as Rerenderers from "./react-rerenderers";

export const AppView = () => {
  /*
   * This returns the instance of **AppModel** class which is defined above.
   *
  const model = Rerenderers.useInstance();
  /*
   * Call the useRerender() hook because we are actually
   * going to make a read-access to the field `counter`
   * in this method. Call `useRerenderer('counter')` causes this component
   * to be rerendered when `fireRerenderers('counter')` is called.
   */
  Rerenderers.useRerenderer("counter");

  return (
    <div id="main-frame">
      <div
        id="main-object"
        /*
         * Note that this performes the read-access to
         * the `counter` field of the class directly.
         */
        className={`square${model.counter}`}

        /*
         * Note that this performes the write-access to
         * the `counter` field of the class directly.
         * This effectively invokes get() method of the class.
         */
        onClick={() => model.counter++}
      >
        <div>{model.counter}</div>
      </div>
      <div id="main-message">Click the Square</div>
    </div>
  );
};

The example above works. And I noticed that, in this way, it is able to cleanly modularize components and their states and the application can scalably be extended.

Rules of useRerenderer() and fireRerenderers()

It is very important to understand when to call useRerenderer() and fireRerenderers().

See the following example:

The Rules of React-Rerenderers.js No.1

import * as rers from "./react-rerenderers";
import * as bs from "react-bootstrap";

export const Value01Reader = () => {
  const model = rers.useInstance();
  rers.useRerenderer("value01");
  return <input value={model.value01} readOnly />;
};

export const Value01Writer = () => {
  const model = rers.useInstance();
  function handleClick() {
    model.value01++;
    rers.fireRerenderers(model, "value01");
  }
  return <bs.Button onClick={handleClick}>Add</bs.Button>;
};

The rules are:

  • Call useRerenderer() if the component makes a read-access to a field of the current associated instance.
  • Call 'fireRerenderers()` if the component makes a write-access to a field of the current associated instance.
  • ID parameter of the functions should match to the name of the field where the component makes an access but it is not mandatory; though it must be unique enough to identify the field.

The principle behind the rules is simple:

  • useRerenderer() marks the component where the hook is called as the specified ID; this process effectively makes a list of components with that specified ID and stores the list on the current associated instance.
  • fireRerenderer() rerenders and refreshes the all components in the list which is stored as the specified ID.

This set of rules is related to the mechanism of the re-rendering process of React.js. It requires the knowledge of the proces in order to understand the set of rules properly.

For further information, see Render and Commit in React.js Official Documentation.

Rules of useInstanceValue() and useInstanceValueSetter()

In the previous section, we have seen when to useRerenderer() and fireRerenderer().

useInstanceValue() and useInstanceValueSetter() are merely helper functions to utilize useInstanceValue() and fireRerenderer().

See their source code:

export function useInstanceValue(key) {
  const instance = useInstance();
  /* const rerender = */ useRerenderer(key);
  return instance[key];
}

export function useInstanceValueSetter(key) {
  const instance = useInstance();
  return function setter(f) {
    if (typeof f !== "function") {
      throw new TypeError("value is not a function");
    }
    instance[key] = f(instance[key]);
    fireRerenderers(instance, key);
  };
}

They only help to conform to the rules which are described in the previous section.

Modularize Modal Dialogs

Implementing Modal Dialogs with React.js is tricky. At the first glance, it seems easy; but it actually isn't. See the following example:

Dialogs with React-Router 1.

In this example, dialogs are implemented with a popular module named react-bootstrap. A confirmation dialog box will pop up when you click the center button and it will automatically navigate to another route after the proceed button is clicked.

You may notice that the dialog appears with an animation while the dialog disappears without the animation. It should be with the animation also when it disappears. But you will notice that its workaround for this issue is not easy.

Understanding this behavior requires an advanced knowledge particularly about where it keeps the current state and where it tries to rebuild React Virtual DOM.

// The Route Definition for the Router
  +-route1
    +-<Dialog1 />
    +-<View1 />
  +-route2
    +-<Dialog2 />
    +-<View2 />

// The Transition of the React Virtual DOM Tree
Step 1. Before the navigation
  +-Router
    +-<Dialog1/>
    +-<View1/>
Step 2. Right after the navigation is triggerd
  +-Router
    +- <Dialog1/> (-) // this will be destroyed node
    +- <View1/>   (-) // this will be destroyed node
    +- <Dialog2/> (+) // this is a newly created node
    +- <View2/>   (+) // this is a newly created node
3. After it navigates to another
  +-Router
    +- <Dialog2/>
    +- <View2/>

The animation which occurs when the dialog disappears is always interrupted because the <Dialog1/> component will be unmounted after Router starts to navigate to the route2 without waiting <Dialog1/> finishes its animation. Therefore, we can conclude that all dialogs should be placed outside the Router. But this requirement invokes more complexity and you will see that the complexity finally becomes out of control.

See the following example: Dialogs with React-Router 2. Provider Hell

There are three things to consider in order to take measurement for the issue of interruption of the animation as we have seen in above:

  • Every dialog must be placed outside the Router.
  • When a dialog is placed outside the router, its state should also be placed outside the Router.
  • The state should also be passed to the caller of the dialog; otherwise the caller cannot trigger the dialog to pop up.

This is actually a very difficult problem. React Router states that every definition of routes should be placed to the global scope.

How can this be achieved?

The only way to pass an arbitrary value to a route is actually using useContext() hook.

But you will be suffered with the second problem. Actually every route is not able to be any descendant of other React Virtual DOM Tree. In short,

const MY_VALUE={};
const ctx = createContext(MY_VALUE);
const router = [ ... /* some-routes */ ];
return (
  <ctx.Provider  >
    <RouterProvider router={router} />
  </ctx.Provider>
);

Unfortunately, the code above does not work. But the good news is, there are a simple workaround; create a pathless route with <Outlet/> as follows:

const MY_VALUE={};
const ctx = createContext(MY_VALUE);
const router = createBrowserRouter(
  createRoutesFromElements(
    <Route element={ <ctx.Provider /><Outlet/></ctx.Provider> }>
      <Route path="/" element={<MyView />} />
    </Route>
  )
);
return (
  <RouterProvider router={router} />
);

This flawlessly works. The workaround will be explained further in the following section.

Good! So we can go through this difficulty, right?! Actually this leads us to another hell. That is the Provider Hell.

This hell is terrible. See the previous example again:

Dialogs with React-Router 2. Provider Hell

AppView.js

  {
    path: "/",
    element: (
      <>
        <Rotate1Provider>
          <Rotate2Provider>
            <Router.Outlet />
          </Rotate2Provider>
        </Rotate1Provider>
      </>
    ),
    children: [
      {
          //...
      },
      //...
    ],
  },

Now we have two providers. That's fine. But the more we create dialogs, the more the nested providers we get. Say we have twenty dialogs, it goes:

  {
    path: "/",
    element: (
      <>
        <Rotate1Provider>
          <Rotate2Provider>
            <Rotate3Provider>
              <Rotate4Provider>
                <Rotate5Provider>
                  <Rotate6Provider>
                    <Rotate7Provider>
                      <Rotate8Provider>
                        <Rotate9Provider>
                          <Rotate10Provider>
                            <Rotate11Provider>
                              <Rotate12Provider>
                                <Rotate13Provider>
                                  <Rotate14Provider>
                                    <Rotate15Provider>
                                      <Rotate16Provider>
                                        <Rotate17Provider>
                                          <Rotate18Provider>
                                            <Rotate19Provider>
                                              <Rotate20Provider>
                                                <Router.Outlet />
                                              </Rotate20Provider>
                                            </Rotate19Provider>
                                          </Rotate18Provider>
                                        </Rotate17Provider>
                                      </Rotate16Provider>
                                    </Rotate15Provider>
                                  </Rotate14Provider>
                                </Rotate13Provider>
                              </Rotate12Provider>
                            </Rotate11Provider>
                          </Rotate10Provider>
                        </Rotate9Provider>
                      </Rotate8Provider>
                    </Rotate7Provider>
                  </Rotate6Provider>
                </Rotate5Provider>
              </Rotate4Provider>
            </Rotate3Provider>
          </Rotate2Provider>
        </Rotate1Provider>
      </>
    ),
    children: [
      {
          //...
      },
      //...
    ],
  },

This is the Provider Hell.

This is where React-Rerenderers's useTransmitter() comes in. See the following example;

Dialogs with React-Router 3. : Eliminate Provider Hell

const routes = [
  {
    path: "/",
    loader: () => {
      return {};
    },
    element: (
      <>
        <Dialog1 />
        <Dialog2 />
        <Router.Outlet />
      </>
    ),
    children: [
      //...
    ],
  }
];

It cuts out the necessity of the providers and flattens the definitions of the dialogs.

With React-Rerenderers's useTransmitter() hook, it is not required to define customized providers. See the following code:

export const Dialog1 = () => {
  const navigate = rr.useNavigate();
  const [show, setShow] = React.useState(false);
  const handlers = {
    show,
    handleClose: (result) => {
      setShow(false);
      if (result) {
        navigate("/" + handlers.to);
      }
    },
    handleShow: () => setShow(true),
    get message() {
      return `Navigate to ${handlers.to}?`;
    },
    to: "bar"
  };

  Rerenderers.useNewTransmitter("route1dialog", handlers); // << See this.

  return (
    <>
      <bs.Modal show={handlers.show} onHide={handlers.handleClose}>
        //....
      </bs.Modal>
    </>
  );
}

After we called the useState() hook, we set the state setter function to an object. Then we passed the object to React-Rerenderers.js's useNewTransmitter() hook with an ID, in this case it is route1dialog.

While the component which calls the useNewTransmitter() hook is mounted somewhere in the React Virtual DOM Tree, you can access to the value via calling useTransmitter() hook with the specified ID route1dialog .

This enables users to access to any hooks (that is, states and state setter functions) from anywhere in the React Virtual DOM Tree without those nested context providers.

How to Use Rerenderers with React-Router

You very likely want to use React-Rerenderers with React-Router. If you are in that case, you might try the following code and notice that it does not work.

const router = [ ... /* some-routes */ ];
return (
  <InstanceProvider factory={() => model} >
    <RouterProvider router={router} />
  </InstanceProvider>
);

This problem roots to the difficulty of using React Context with React Router. See the following example.

export const ctx = React.createContext("FOO");
const router = createBrowserRouter([ ... ]);
const Main =()=>{
  return (
    <ctx.Provider value={"BAR"}>
      <RouterProvider router={router} />
    </ctx.Provider>
  );
}

It is not able to access to the value which is set to <ctx.Provider /> if you place the provider outside the route object tree.

The context consumer has to be a direct descendant of the context provider. In React-Router, your component will be a direct descendant of Route component which is the case that useContext() cannot corporate with.

The only workaround which I could find in the net is mentioned in this post in React-Router Remix's GitHub Repository.

export const ctx = React.createContext("FOO");
const router = createBrowserRouter(
  createRoutesFromElements(
    <Route element={
      <ctx.Provider value={"BAR"} >
        <Outlet />
      </ctx.Provider>
    }>
      <Route path="/" element={<AppView />} />
    </Route>
  )
);
const Main =()=>{
  return (
    <RouterProvider router={router} />
  );
}

According to this post, it is necessary to create a pathless route and place others as its children. Otherwise useContext() hook cannot access to the current value that is set to <Provider/> component.

See this post for further information.

React-Rerenderers.js's <InstanceProvider/> uses useContext() hook. That is, the instance consumer has to be a direct descendant of the instance provider.

const router = [ ... /* some-routes */ ];
return (
  <InstanceProvider factory={() => model} >
    <RouterProvider router={router} />
  </InstanceProvider>
);

The code above does not work as expected.

Unless the <InstanceProvider/> is placed as follows, it will not be able to retrieve its current state.

const router = createBrowserRouter(
  createRoutesFromElements(
    <Route element={ <InstanceProvider factory={() => model} /> }>
      <Route path="/" element={<AppView />} />
    </Route>
  )
);
return (
  <RouterProvider router={router} />
);

Kombucha.js ES6 Module Convention in React.js (KOMESMCOIR)

We defines a convention which should be followed in all modules in a Kombucha.js frontend application. It has a requirement to a module to implement some specific named fields and methods. It also has a requirement how those modules should be named.

We call this convention as KOMESMCOIR convention.

Design Goal

The design purpose of KOMESMCOIR is to implement scalable development of frontend applications especially with React-Router.

Modularizing components with React-Router is often complicated and tricky. And the solutions are tent to vary among the developers; so we decided to define the unique convention for modules which are used in React.js applications to resolve style conflicts.

Filename Convention

Every module should be named starting with unit_. Use underscore as word separators. For example:

  • unit_main.js
  • unit_error_dialog.js
  • unit_user_managers.js

Fields to be Defined

See the following example:

/*
 * Define components that should be placed outside the router here.
 * These are usually dialogs.
 */
export const dialogs = [
  <ErrorDialog />,
  <FooDialog />,
  <BarDialog />,
],


/*
 * For further information about data contents of `routes`
 * please see React.js' documentation
 * https://reactrouter.com/en/main/routers/create-browser-router
 */
export const routes = [
  {
    path: "/",
    element: <Root />,
    loader: rootLoader,
    children: [
      {
        path: "team",
        element: <Team />,
        loader: teamLoader,
      },
    ],
  },
];

/*
 * Export the path to the main route.
 */
export const path = '/';



/*
 * Export an object which consists all exported variables.
 */
export default {
  dialogs,
  path,
  routes,
}

KOMESMCOIR modules must have three fields:

API Reference

\<InstanceProvider factory={} />

<InstanceProvider/> can share the current object which all states in an application should be stored. The attribute factory should be a function which returns the current object.

Opposing to the name factory suggests, in most case, it should be as follows:

export const myModel = new MyModel();
const Main = ()=>{
  return (
    <InstanceProvider factory={()=>myModel} >
      <MyView/>
    </InstanceProvider>
  );
};

Not as follows:

const Main = ()=>{
  return (
    <InstanceProvider factory={()=>new MyModel()} >
      <MyView/>
    </InstanceProvider>
  );
};

The object should be located on the global scope because actions and loaders on your routers are very likely placed on the global scope. If your model is placed on React.js's state, there is no way to access to it from your actions and loaders.

Usage of <InstanceProvider/> is not mandatory. In case you haven't specified your current object, it defaults to GLOBAL_INSTANCE as mentioned later.

Attributes

  • factory : function Specify a function which returns the current instance value to associate with.

useInstance()

useInstance() hook returns the current instance which is associated to the React Virtual DOM Tree where the caller component is belonging to. If no instance is associated, it returns GLOBAL_INSTANCE.

GLOBAL_INSTANCE is described in the following section.

GLOBAL_INSTANCE

GLOBAL_INSTANCE is the default instance where there is no current instance which is associated to the React Virtual DOM Tree where the current component is belonging to.

useInstanceValue( fieldname : string )

useInstanceValue() returns the value of the specified field on the current instance which is associated to the React Virtual DOM Tree where the caller component is belonging to.

This is a helper function which is meant to simplify the calling process of useRerenderer() and fireRerenderers().

Parameters

  • fieldname : string Specify the field name to get the current value

useInstanceValueSetter( fieldname : string )

useInstanceValueSetter() returns a setter function to set a value of the specified field on the current instance which is associated to the React Virtual DOM Tree where the caller component is belonging to.

This is a helper function which is meant to simplify the calling process of useRerenderer() and fireRerenderers().

Parameters

  • fieldname : string Specify the field name to set a new value

useRerenderer( id:any )

useRerenderer() hook function marks the caller component with the specified ID

Parameters

  • id : any Specify the ID to mark as.

fireRerenderers(instance:object, id:any)

fireRerenderers() refreshes and re-renders the components which is associated to the specified ID.

Parameters

  • instance : any Specify the current instance.
  • id : any Specify the ID of the components to be re-rendered.

useNewTransmitter( id:any, f:function )

useNewTransmitter() sets a value to the specified field on the current associated instance only while the caller component is mounted to the React Virtual DOM Tree in order to share the value with the components anywhere on the associated tree.

The value can be obtained by calling useTransmitter() and getTransmitter() while the component is mounted.

This hook is meant to be used to share states and state setter functions between components on the other part of the tree.

Parameters

  • id:any Specify the ID which is used for identify the value.
  • f:function Specify the function which returns the value which should be shared with other components.

useTransmitter( id:any )

useTransmitter() retrieves the current value which is registered by useNewTransmitter() hook. useTransmitter() returns the value only when the caller of useNewTransmitter()hook is mounted; otherwise it returnsnull`.

Parameters

  • id:any Specify the ID which is used for identify the value.

getTransmitter( instance:any, id:any )

getTransmitter() is a non-hook function which has the exactly same functionality with useTransmitter() function.

useRerender()

useRerender() is the lowest-level basic function of React-Rerenderers. The return value is a function. Call the function to invoke rerendering process of the component which calls the useRerender() hook.

Return Value

  • a function to rerender the component which calls the useRerender() hook.

🌈 Conclusion 🌈

I am not sure this is an appropriate usage React.js nor I even don't think this is a correct usage of React.js since this usage is a kind of an attempt of denial of the React.js's mechanism for the automatic update detection.

But in this way, I believe, the number of issues which you often encounter when you build a comparably larger application can be easily avoided.

I am worrying that nobody understand the meaning and the effectiveness of this module because I even think this module is very weird; but it works.

Additionally, I am from Japan; my English ability is quite limited. Please excuse my obscured English and I hope my English is good enough for everyone to understand my idea.

Thank you very much and see you soon.

History

as react-hooks

  • v1.0.0 Released
  • v1.0.1 Updated README.md
  • v1.0.2 Updated README.md (Tue, 08 Aug 2023 10:41:08 +0900)
  • v1.0.3 Updated README.md (Tue, 08 Aug 2023 10:49:17 +0900)
  • v1.0.4 Updated README.md (Tue, 08 Aug 2023 16:24:05 +0900)
  • v1.0.5 Updated README.md (Wed, 09 Aug 2023 17:23:53 +0900)
  • v1.0.6 Updated README.md (Wed, 09 Aug 2023 20:30:01 +0900)
  • v1.0.7 Removed JSX syntax (Fri, 11 Aug 2023 10:56:13 +0900)
  • v1.0.8 Exported useRerender() (Sat, 12 Aug 2023 15:57:48 +0900)
  • v1.0.9 add useNewSharedState() (Fri, 01 Mar 2024 14:49:04 +0900)

as react-rerenderers.js

  • After react-hooks was released, rerenderers.js was forked from the module react-hooks. Since then rerenderers.js have been developed in a different application.
  • On Aug 24, 2023, the new repository react-rerenderers.js was started.
  • At the time react-rerenderers.js was started, it was not registered to https://npmjs.org/
  • (Wed, 18 Oct 2023 21:21:25 +0900) Release v1.0.0.

[]: <> " vim: set ts=2 sts=2 spell : "

1.0.9

2 months ago

1.0.0

7 months ago