Categories
React Hooks

Top React Hooks — State and Wait

Hooks contains our logic code in our React app.

We can create our own hooks and use hooks provided by other people.

In this article, we’ll look at some useful React hooks.

react-wait

The react-wait package lets us display something while we’re waiting for something to load.

We can install it by running:

yarn add react-wait

Then we can use it by writing:

index.js

import React from "react";
import ReactDOM from "react-dom";
import { Waiter } from "react-wait";

import App from "./App";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Waiter>
    <React.StrictMode>
      <App />
    </React.StrictMode>
  </Waiter>,
  rootElement
);

App.js

import React from "react";
import { useWait } from "react-wait";

export default function App() {
  const { isWaiting } = useWait();
  return (
    <div>
      {isWaiting("creating item") ? "Creating Item..." : "Nothing happens"}
    </div>
  );
}

We wrap our app with the Waiter component.

This way, we can call useWait hook to return an object with the isWaiting method.

Then we can call isWaiting to show different things depending on whether the app is busy or not.

We can control the busy state with other functions.

For instance, we can write:

index.js

import React from "react";
import ReactDOM from "react-dom";
import { Waiter } from "react-wait";

import App from "./App";

const rootElement = document.getElementById("root");
ReactDOM.render(
  <Waiter>
    <React.StrictMode>
      <App />
    </React.StrictMode>
  </Waiter>,
  rootElement
);

App.js

import React from "react";
import { useWait, Waiter } from "react-wait";

export default function App() {
  const { startWaiting, endWaiting, isWaiting, Wait } = useWait();

  return (
    <button
      onClick={() => startWaiting("creating")}
      disabled={isWaiting("creating")}
    >
      <Wait on="creating" fallback={<div>Creating!</div>}>
        Create
      </Wait>
    </button>
  );
}

We call the useWait hook and get more properties in the returned object.

startWaiting lets us turn on the busy state.

The string identifies what it’s doing.

isWaiting indicates whether the 'creating' busy state is on.

We have the Wait component with the on prop to watch for the creating busy state.

fallback has the items to load when it’s busy.

react-window-communication-hook

The react-window-communication-hook package lets us create a communication channel without our component.

We can install it by running:

npm i react-window-communication-hook

Then we can write:

import React from "react";
import useBrowserContextCommunication from "react-window-communication-hook";

export default function App() {
  const [communicationState, postMessage] = useBrowserContextCommunication(
    "channel"
  );

  const [status, setStatus] = React.useState("on");

  function turnOff() {
    setStatus("off");
    postMessage("off");
  }

  const isOff = [communicationState.lastMessage, status].includes("off");

  return (
    <div className="App">
      <h1>{isOff ? "off" : "on"}</h1>
      <button onClick={turnOff}>turn off</button>
    </div>
  );
}

We imported the useBrowserContextCommunication hook to return the communicateState and postMessage variables.

communicationState has the communication state.

It has the lastMessage with the last message that was sent with postMessage .

postMessage is a function that lets us send a message.

reaktion

The reaktion package provides us with a gook that uses the same API has useState .

To install it, we can run:

yarn add reaktion

Then we can use it by writing:

index.js

import React from "react";
import ReactDOM from "react-dom";
import { Reaktion } from "reaktion";

import App from "./App";

const rootElement = document.getElementById("root");

const initialState = { name: "mary" };

ReactDOM.render(
  <Reaktion initialState={initialState}>
    <React.StrictMode>
      <App />
    </React.StrictMode>
  </Reaktion>,
  rootElement
);

App.js

import React from "react";
import { useStore } from "reaktion";

export default function App() {
  const [name, setName] = useStore("name");

  return <button onClick={() => setName("james")}>Hello {name}</button>;
}

We wrap the Reaktion component around our App so that we can use the useStore hook in our app.

initialState has the initial state.

It takes the property of the state we want to get and set.

The array has name and setName , which is the value and the function to set the value respectively.

Conclusion

react-wait lets us display something when our app is busy.

react-window-communication-hook lets us communicate within a component.

reaktion lets us set states similar to useState .

Categories
React Hooks

Top React Hooks — Shared State and Visibility

Hooks contains our logic code in our React app.

We can create our own hooks and use hooks provided by other people.

In this article, we’ll look at some useful React hooks.

@rooks/use-visibility-sensor

The @rooks/use-visibility-sensor package lets us detect the visibility of our component.

To install it, we can run:

npm install --save @rooks/use-visibility-sensor

Then we can use it by writing:

import React from "react";
import useVisibilitySensor from "@rooks/use-visibility-sensor";

export default function App() {
  const ref = React.useRef(null);
  const { isVisible, visibilityRect } = useVisibilitySensor(ref, {
    intervalCheck: false,
    scrollCheck: true,
    resizeCheck: true
  });
  return (
    <div ref={ref}>
      <p>{isVisible ? "Visible" : "Not Visible"}</p>
      <p>{JSON.stringify(visibilityRect)}</p>
    </div>
  );
}

We use the useVisibilitySensor with a ref that’s passed to the element we want to check the visibility for.

The 2nd argument is an object with various options.

intervalCheck is an integer or boolean that let us whether we check for visibility periodically.

If it’s a number then it’s the interval between each check in milliseconds.

scrollCheck is a boolean to determine whether to check for scroll behavior or not.

resizeCheck lets us check for resize if it’s true .

There’re other options for throttling and more.

Resynced

The Resynced library is a library that lets us share states between multiple components.

To install it, we can run:

yarn add resynced

Then we can use it by writing:

import React from "react";
import { createSynced } from "resynced";

const initialState = 0;
const [useSyncedState] = createSynced(initialState);

const Counter = () => {
  const [count] = useSyncedState();

  return (
    <div>
      <p> {count}</p>
    </div>
  );
};

export default function App() {
  const [_, setCount] = useSyncedState();

  return (
    <div>
      <button onClick={() => setCount(s => s + 1)}>increment</button>
      <Counter />
    </div>
  );
}

We call createSynced with th initial state to return an array with the useSyncedState hook.

Then we use the returned hook in our components.

It returns an array with the state and the function to set the state in this order.

We call setCount to set the state in App

And we get the count state in Counter .

RRH

RRH provides hooks that we can use to get and set React Redux state data.

To install it, we can run:

npm install rrh --save

or

yarn add rrh

Then we can use it by wiring:

import React from "react";
import { useProvider, useSelector } from "rrh";
import { createLogger } from "redux-logger";
import { applyMiddleware } from "redux";

const logger = createLogger();

const initState = {
  count: 0
};

const reducer = (state, action) => {
  switch (action.type) {
    case "INCREMENT":
      return { count: state.count + 1 };
    default:
      return state;
  }
};

const Counter = () => {
  const selected = useSelector(
    {},
    (dispatch, props) => ({
      increment: () => dispatch({ type: "INCREMENT", payload: 1 })
    }),
    (state, props) => ({ count: state.count }),
    state => [state.count]
  );

  return (
    <div>
      {selected.count}
      <button onClick={selected.increment}>INC</button>
    </div>
  );
};

export default function App() {
  const Provider = useProvider(() => ({
    reducer,
    preloadedState: { count: 1 },
    storeEnhancer: applyMiddleware(logger)
  }));
  return (
    <div>
      <Provider>
        <Counter />
        <Counter />
      </Provider>
    </div>
  );
}

We create an object with the initial state with the initState object.

And we create the createLogger function to return the logger .

Then we create our reducer to set the state.

In Counter , we call the useSelector hook.

The first argument of it is the props.

The 2nd argument has a function to return an object with functions to dispatch actions.

The 3rd argument maps the state the way we want.

The 4th argument has a function with the dependencies to watch for.

The state is in the selected variable.

In App , we wrap our components that we want to make accessible to the store with the Provider .

The Provider is created with the useProvider hook that takes a function.

The function returns an object with the reducer , preloadedState , and storeEnhancer .

reducer has the reducer.

preloadedState has the initial state.

storeEnhancer has the Redux middleware we want to run.

Conclusion

@rooks/use-visibility-sensor lets us detect visibility.

Resynced lets us create a shared state for our components.

RRH lets us use Redux with hooks.

Categories
React Hooks

Top React Hooks — Renders and States

Hooks contains our logic code in our React app.

We can create our own hooks and use hooks provided by other people.

In this article, we’ll look at some useful React hooks.

react-use

The react-use library is a big library with many handy hooks.

useMediatedState

We can use the useMediatedState hook is a hooks that works like useState , but we can run a callback to manipulate the state before returning it.

To use it, we can write:

import React from "react";
import { useMediatedState } from "react-use";

const inputMediator = s => s.replace(/s+/g, "");

export default function App() {
  const [state, setState] = useMediatedState(inputMediator, "");

  return (
    <div>
      <input
        type="text"
        min="0"
        max="10"
        value={state}
        onChange={ev => {
          setState(ev.target.value);
        }}
      />
    </div>
  );
}

to use the useMediatedState hook to remove the spaces in the text we typed in before returning the state .

The first argument is the callback to manipulate the state and the 2nd is the initial value.

useFirstMountState

The useFirstMountState hook lets us check if the component is just mounted.

It’ll return true if it’s just mounted and false otherwise.

For instance, we can use it by writing:

import React from "react";
import { useFirstMountState } from "react-use";

export default function App() {
  const isFirstMount = useFirstMountState();

  return (
    <div>
      <span>{isFirstMount.toString()}</span>
    </div>
  );
}

It’ll show true if it’s first mounted and false otherwise.

It takes no arguments.

useRendersCount

We can use the useRendersCount hook to track the renders count including the first render.

For instance, we can write:

import React from "react";
import { useRendersCount, useUpdate } from "react-use";

export default function App() {
  const update = useUpdate();
  const rendersCount = useRendersCount();
  return (
    <div>
      <span>render count: {rendersCount}</span>
      <br />
      <button onClick={update}>refresh</button>
    </div>
  );
}

We have a button that calls the update function returned by useUpdate to update our component.

It’ll cause a re-render so the rendersCount will increase by 1.

useGlobalState

The useGlobalState hook lets us create a global state that we can share between components.

For instance, we can write:

import React from "react";
import { createGlobalState } from "react-use";

const useGlobalValue = createGlobalState(0);

const Increase = () => {
  const [value, setValue] = useGlobalValue();

  return <button onClick={() => setValue(value + 1)}>increase</button>;
};

const Decrease = () => {
  const [value, setValue] = useGlobalValue();

  return <button onClick={() => setValue(value - 1)}>decrease</button>;
};

export default function App() {
  const [value] = useGlobalValue();
  return (
    <div>
      <p>{value}</p>
      <Increase />
      <Decrease />
    </div>
  );
}

We called the createGlobalState hook with an initial value to return the useGlobalValue hook.

It returns an array with the value and setValue variables.

value has the state value and setValue has the function to set the value .

We use the useGlobalValue hook in all the components.

In Increase , we used it to increase the value .

In Decrease , we used it to decrease the value .

In App , we only used the hook to get the value .

Conclusion

The react-use library has hooks to get and set states in various ways.

We can also use it to get render count and state.

Categories
React Hooks

Top React Hooks — Portals and Redux

Hooks contains our logic code in our React app.

We can create our own hooks and use hooks provided by other people.

In this article, we’ll look at some useful React hooks.

useMiddleware

The react-usemiddleware hook lets us create a state with Redux middlewares.

To install it, we run:

npm install react-usemiddleware --save

or:

yarn add react-usemiddleware

Then we can use it by writing:

import React from "react";
import { createLogger } from "redux-logger";
import useMiddleware from "react-usemiddleware";

const logger = createLogger();
const middlewares = [logger];

const initState = {
  count: 0
};

const reducer = (state, action) => {
  switch (action.type) {
    case "INCREMENT":
      return { count: state.count + 1 };
    default:
      return state;
  }
};

export default function App() {
  const [state, dispatch] = useMiddleware(reducer, initState, middlewares);
  return (
    <div className="App">
      <button onClick={() => dispatch({ type: "INCREMENT" })}>increment</button>
      <span>{state.count}</span>
    </div>
  );
}

We have the redux logger that we created with the createLogger function.

We also have the initState with the initial state.

And we created a reducer that’s the usual reducer format.

We pass in the reducer , initState , and middlewares in the useMiddleware hook.

It returns the state with the state from the Redux store and the dispatch function that lets us dispatch an action.

We have the state.count with our count state from the store.

react-useportal

The react-useportal package lets us create portals, which are elements that render outside their usual hierarchy.

To install it, we run:

yarn add react-useportal

or:

npm i -S react-useportal

Then we can use it by writing:

import React from "react";
import usePortal from "react-useportal";

export default function App() {
  const { Portal } = usePortal();

  return <Portal>hello world</Portal>;
}

We just return the Portal component by calling the usePortal hook.

Then we can pass in anything in there.

The items will be rendered in the body element.

We can also render the items inside in another element.

For instance, we can write:

import React from "react";
import usePortal from "react-useportal";

export default function App() {
  const { Portal } = usePortal({
    bindTo: document && document.getElementById("hello-world")
  });

  return <Portal>hello world</Portal>;
}

to render the items inside Portal in the element with ID hello-world .

We can also use states to render the portal dynamically.

For instance, we can write:

import React from "react";
import usePortal from "react-useportal";

export default function App() {
  const { openPortal, closePortal, isOpen, Portal } = usePortal();

  return (
    <>
      <button onClick={openPortal}>Open</button>
      {isOpen && (
        <Portal>
          <div>
            <button onClick={closePortal}>Close</button>
            <p>hello world</p>
          </div>
        </Portal>
      )}
    </>
  );
}

The usePortal hook returns an object with the variables.

The Portal is the portal.

isOpen checks whether the portal is attached or not.

openPortal is a function that set isOpen to true .

closePortal is a function that sets isOpen to false .

We can also press Esc to remove the portal.

This is handy for modals.

Conclusion

The useMiddleware hook lets us use Redux middlewares to our apps.

We can use react-useportal to add portals to our app.

Categories
React Hooks

Top React Hooks — Observables and Hooks

Hooks contains our logic code in our React app.

We can create our own hooks and use hooks provided by other people.

In this article, we’ll look at some useful React hooks.

React Hooks for RxJS

The React Hooks for RxJS library lets us use Rxjs observables in our React components.

To install it, we can run:

npm i --save rxjs-hooks

or:

yarn add rxjs-hooks

We can use it by writing:

import React from "react";
import { useObservable } from "rxjs-hooks";
import { interval } from "rxjs";
import { map } from "rxjs/operators";

export default function App() {
  const value = useObservable(() => interval(2000).pipe(map(val => val * 2)));

  return (
    <div className="App">
      <h1>{value}</h1>
    </div>
  );
}

We use the interval observable with the useObservable hook.

It returns the value of the observable.

The pipe operator lets us modify the value generated from the interval observable.

It also comes with the useEventCallback hook to let us watch for event object changes.

For instance, we can write:

import React from "react";
import { useEventCallback } from "rxjs-hooks";
import { map } from "rxjs/operators";

export default function App() {
  const [clickCallback, [description, x, y]] = useEventCallback(
    event$ =>
      event$.pipe(
        map(event => [event.target.innerHTML, event.clientX, event.clientY])
      ),
    ["nothing", 0, 0]
  );

  return (
    <div className="App">
      <p>
        click position: {x}, {y}
      </p>
      <p>{description} was clicked.</p>
      <button onClick={clickCallback}>click foo</button>
      <button onClick={clickCallback}>click bar</button>
      <button onClick={clickCallback}>click baz</button>
    </div>
  );
}

We called the useEventCallback hook with a callback that takes th event$ observable.

It returns the piped results returned from the pipe operator.

map lets us return an object we can get the click event object properties from.

The hook returns an array with the clickCallback that we can use as click handlers.

The 2nd entry is the click event object.

The 3rd argument is an array with the initial values of the properties in the click event object.

Scroll Data Hook

The Scroll Data Hook library lets us return information about scroll speed, distance, direction, and more.

To use it, we can install it by running:

yarn add scroll-data-hook

Then we can use it by writing:

import React from "react";
import { useScrollData } from "scroll-data-hook";

export default function App() {
  const {
    scrolling,
    time,
    speed,
    direction,
    position,
    relativeDistance,
    totalDistance
  } = useScrollData({
    onScrollStart: () => {
      console.log("Started scrolling");
    },
    onScrollEnd: () => {
      console.log("Finished scrolling");
    }
  });

  return (
    <div>
      <div style={{ position: "fixed" }}>
        <p>{scrolling ? "Scrolling" : "Not scrolling"}</p>
        <p>Scrolling time: {time} milliseconds</p>
        <p>Horizontal speed: {speed.x} pixels per second</p>
        <p>Vertical speed: {speed.y} pixels per second</p>
        <p>
          Position: {position.x} {position.y}
        </p>
        <p>
          Direction: {direction.x} {direction.y}
        </p>
        <p>
          Relative distance: {relativeDistance.x}/{relativeDistance.y}
        </p>
        <p>
          Total distance: {totalDistance.x}/{totalDistance.y}
        </p>
      </div>
      <div>
        {Array(1000)
          .fill()
          .map((_, i) => (
            <p key={i}>{i}</p>
          ))}
      </div>
    </div>
  );
}

We call the useScrollData hook with the object that has a callback that runs when we scroll.

onScrollStart runs when we start scrolling.

onScrollEnd runs when we stop scrolling.

The hook returns an object with various properties.

scrolling is a boolean to indicate whether we’re scrolling.

time is how long we scrolled.

speed is the scrolling speed.

direction is the scrolling direction.

position is the scrolling position.

Conclusion

React Hooks for RxJS lets us use Rxjs observables in our React app.

Scroll Data Hook lets us watch for different kinds of scrolling data in our app.