Categories
React Hooks

Top React Hooks — Touch and Context

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.

Melting Pot

Melting Pot has a bunch of hooks that we can use in our React app.

It’s a utility library with many hooks.

To install it, we run:

npm install @withvoid/melting-pot --save

or:

yarn add @withvoid/melting-pot

The useTouch hook lets us watch for the touching of an element.

To use it, we can write:

import React from "react";
import { useTouch } from "@withvoid/melting-pot";

export default function App() {
  const { touched, bind } = useTouch();

  return (
    <div {...bind}>
      <p>Touch this</p>
      <p>
        Status: <span>{String(touched)}</span>
      </p>
    </div>
  );
}

We use the useTouch hook, which returns an object with the touched and bind properties.

touched indicates whether the item is touched.

bind is an object which we use as props for the element we want to watch for touches.

The useUpdate hook us a replacement of the componentDidUpdate method in React class components.

We can use it by writing:

import React from "react";
import { useUpdate } from "@withvoid/melting-pot";

export default function App() {
  const [count, setCount] = React.useState(0);

  useUpdate({
    action: () => console.log("state was updated"),
    exit: () => console.log("exiting")
  });
  return (
    <div>
      <button onClick={() => setCount(count + 1)}>{count}</button>
    </div>
  );
}

We can use the useUpdate hook to watch for state updates.

We used the hook with an object passed into it.

action runs when the state is updated.

exit runs when it rerenders.

The useWindowScrollPosition hook lets us watch for the scroll position on our page.

We can use it by writing:

import React from "react";
import { useWindowScrollPosition } from "@withvoid/melting-pot";

export default function App() {
  const scrollPosition = useWindowScrollPosition();

  return (
    <div>
      <p style={{ position: "fixed" }}>{JSON.stringify(scrollPosition)}</p>
      {Array(1000)
        .fill()
        .map((_, i) => (
          <p>{i}</p>
        ))}
    </div>
  );
}

We watch for the scroll position with the hook.

It has the x and y properties to show the scroll position’s x and y coordinates.

Now as we scroll, we’ll see the position update.

The useWindowSize hook lets us watch for the size of the window.

To use it, we write:

import React from "react";
import { useWindowSize } from "[@withvoid/melting-pot](http://twitter.com/withvoid/melting-pot "Twitter profile for @withvoid/melting-pot")";

export default function App() {
  const { width, height } = useWindowSize();
  return (
    <div>
      {width} x {height}
    </div>
  );
}

The width and height has the width and height of the window.

Constate

The Constate library lets us share data between components by lifting the state to the top with the context API.

We can install it by running:

npm i constate

or:

yarn add constate

Then we can write:

import React, { useState } from "react";
import constate from "constate";

function useCounter() {
  const [count, setCount] = useState(0);
  const increment = () => setCount(prevCount => prevCount + 1);
  return { count, increment };
}

const [CounterProvider, useCounterContext] = constate(useCounter);

function Button() {
  const { increment } = useCounterContext();
  return <button onClick={increment}>increment</button>;
}

function Count() {
  const { count } = useCounterContext();
  return <span>{count}</span>;
}

export default function App() {
  return (
    <div>
      <CounterProvider>
        <Count />
        <Button />
      </CounterProvider>
    </div>
  );
}

to use it.

We created ou own useCounter hook to update the count state.

It returns the state and a function to update it.

Then we use constate to create a context with the hook.

It returns the context provider and a hook to use the context.

Then in Button and Counter , we call useCounterContext to use the state.

It just returns what we return in the useCounter hook.

Then we can use the components together in App without passing props around.

The CounterProvider is the context provider and it has to wrap around everything.

Conclusion

Melting Pot has various useful hooks.

Constant lets us share context state in an orderly way.

Categories
React Hooks

Top React Hooks — State Utilities

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.

moment-hooks

The moment-hooks library is a library that comes with various utility hooks that we can use.

We can install it with:

yarn install moment-hooks

The useDebounce hook lets us add denounce functionality to our app.

It can be used to reduce the number of times a state is updated.

For instance, we can write:

import React from "react";
import { useDebounce } from "moment-hooks";

export default function App() {
  const [inputValue] = React.useState("something");
  const debouncedInputValue = useDebounce(inputValue, 100);

  return <div className="app">{debouncedInputValue}</div>;
}

We have the useDebounce hook that takes the inputValue state.

The 2nd argument is the number of milliseconds to delay the update of the state.

The useWindowSize hook lets us get the width and height of the window.

To use it, we write:

import React from "react";
import { useWindowSize } from "moment-hooks";

export default function App() {
  const { width, height } = useWindowSize();

  return (
    <div className="app">
      {width} x {height}
    </div>
  );
}

We call the useWindowSize hook to get the window’s width and height.

Then we can use those anywhere.

The useWhyDidYouUpdate hook gets the reason why a component has been updated.

It’s useful for debugging our components.

To use it, we can write:

import React from "react";
import { useWhyDidYouUpdate } from "moment-hooks";

const Foo = props => {
  useWhyDidYouUpdate("Register", props);

  return <div />;
};

export default function App() {
  return (
    <div className="app">
      <Foo foo="bar" />
    </div>
  );
}

Then since we have the useWhyDidYouUpdate hook has been called with 'Register' and props , it’ll log the value when the props are changed.

We’ll get the old and new value logged.

Nice Hooks

Nice Hooks is a set of hooks that does various things.

To install it, we run:

npm install nice-hooks

Then we can use the hooks that comes with it.

The useStateCB hook lets us get and set a state.

To use it, we can write:

import React from "react";
import { useStateCB } from "nice-hooks";

export default function App() {
  const [getCount, setCount] = useStateCB(0);

  function doSomething() {
    console.log(getCount());
  }

  return (
    <div>
      <p>{getCount()}</p>
      <button onClick={() => setCount(getCount() + 1, doSomething)}>
        Increase
      </button>
    </div>
  );
}

We use the useStateCB hook to return a getter and setter function for a state.

When we click the button, we call setCount to set the count.

doSomething is run after the state change is done.

getCount gets the count state.

The useSingleState hook is another hook that lets us get and set the state.

For instance, we can write:

import React from "react";
import { useSingleState } from "nice-hooks";

export default function App() {
  const [state, setState] = useSingleState({
    count: 0
  });

  function doSomething() {
    console.log(state.count);
  }

  return (
    <div>
      <p>{state.count}</p>

      <button
        type="button"
        onClick={() =>
          setState(
            {
              count: state.count + 1
            },
            doSomething
          )
        }
      >
        Increase
      </button>
    </div>
  );
}

useSingleState is another hook that returns that state and a setter for the state respectively.

setState takes an object to update the state.

It also takes a callback that runs when the state update is done.

Conclusion

monent-hooks and Nice Hooks are libraries that provide us with many hooks.

Categories
React Hooks

Top React Hooks — States and Requests

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.

Hookstate

We can use the Hookstate hook to change global and local state in our app.

To use it, we run:

npm install --save @hookstate/core

or:

yarn add @hookstate/core

to install it.

Then we can manage global state by writing:

import React from "react";
import { createState, useState } from "@hookstate/core";
const globalState = createState(0);

export default function App() {
  const state = useState(globalState);
  return (
    <>
      <p>Counter value: {state.get()}</p>
      <button onClick={() => state.set(p => p + 1)}>Increment</button>
    </>
  );
}

We create a global state object with the createState function and then pass it into the Hookstate’s useState hook.

Then we can use get and set to get and set the state respectively.

To change local state, we can write:

import React from "react";
import { useState } from "@hookstate/core";

export default function App() {
  const state = useState(0);
  return (
    <>
      <p>Counter value: {state.get()}</p>
      <button onClick={() => state.set(p => p + 1)}>Increment</button>
    </>
  );
}

The only difference is that we pass the state value straight into the useState hook.

States can be nested.

For example, we can write:

import React from "react";
import { useState, self } from "@hookstate/core";

export default function App() {
  const state = useState([{ name: "Untitled" }]);

console.log(state);
  return (
    <>
      {state.map((task, index) => (
        <p>
          {task.name.get()} {index}
        </p>
      ))}
      <button onClick={() => state[self].merge([{ name: "Untitled" }])}>
        add task
      </button>
    </>
  );
}

We use the useState hook with an array.

To add new value to the array, we use the state[self] object’s merge method to add an entry to it.

Then we can get the entry by using the property’s get method as we did in the map callback.

We can also add scoped, async, and recursive states.

We can use the @jzone/react-request-hook to help us make requests easier.

We can install it by running:

npm install @jzone/react-request-hook

or:

yarn add @jzone/react-request-hook

Then we can use it by writing:

import React from "react";
import useFetchData from "@jzone/react-request-hook";
import axios from "axios";

export default function App() {
  const [{ data, isLoading, error }, fetchData] = useFetchData(data =>
    axios.get("https://api.agify.io/?name=michael", { params: data })
  );

  React.useEffect(() => {
    fetchData();
  }, [fetchData]);

  if (!data) {
    return !error ? <div>loading...</div> : <div>error</div>;
  }

  return (
    <div>
      <p>{JSON.stringify(data)}</p>
    </div>
  );
}

We imported the useFetchData hook to import the hook.

Also, we installed Axios to use that as an HTTP client.

Then we use the fetchData function returned by the hook to get the data.

The data has the response data.

So we can render that the way we want.

It also returns the isLoading state to indicate loading.

error has the error.

We can customize it for other kinds of requests.

Conclusion

Hookstate is a useful hook for managing states.

@jzone/react-request-hook is a hook that lets us get data easier.

Categories
React Hooks

Top React Hooks — State Management

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.

Conuse

Conuse is a state management library that lets us share state between components with the Context API.

We can use it by running:

npm i conuse

or:

yarn add conuse

to install it.

Then we can use it by writing:

import React, { useState } from "react";
import createConuse from "conuse";

const useCounter = () => {
  const [count, setCount] = useState(0);
  const increment = () => setCount(prevCount => prevCount + 1);
  return { count, increment };
};

const { ConuseProvider, useConuseContext } = createConuse({
  counter: useCounter
});

function Button() {
  const { increment } = useConuseContext("counter");
  return <button onClick={increment}>increment</button>;
}

function Count() {
  const { count } = useConuseContext("counter");
  return <span>{count}</span>;
}

export default function App() {
  return (
    <ConuseProvider>
      <Count />
      <Button />
    </ConuseProvider>
  );
}

We have our useCounter ook which returns the count state and the increment function to update the count.

Then we use the createConuse function to create our context provider and the hook to use the context.

We pass our useCounter hook into the object and set that as the value of property.

Then we can use the context with the given name by using the useConuseContext hook with the given string in the Button component

We use the increment function which is the same one we returned in useCounter .

Likewise, the Count component gets the state from the same useConuseContext hook and render the count.

Then in App , we [put everything together with the ConuseProvider wrapping around everything.

ConuseProvider is the context provider, so that’ll be used for sharing the states.

Easy Peasy

Easy Peasy is a package that lets us manage state easily for our React app.

To install it, we run:

npm install easy-peasy

to install it.

Then we can use it by writing:

import React, { useState } from "react";
import {
  createStore,
  action,
  useStoreState,
  useStoreActions,
  StoreProvider
} from "easy-peasy";

const store = createStore({
  todos: {
    items: ["eat", "drink", "sleep"],
    add: action((state, payload) => {
      state.items.push(payload);
    })
  }
});

function TodoList() {
  const todos = useStoreState(state => state.todos.items);
  const add = useStoreActions(actions => actions.todos.add);
  return (
    <div>
      {todos.map((todo, idx) => (
        <div key={idx}>{todo}</div>
      ))}
      <button onClick={() => add("new task")}>add</button>
    </div>
  );
}

export default function App() {
  return (
    <StoreProvider store={store}>
      <TodoList />
    </StoreProvider>
  );
}

We create a store object with the createStore function.

The todos is the state.

items has the items.

add is an action that we created.

We create an action with the action function.

It has a callback to update the state.

We get the state from the state parameter and do stuff to it.

Then we created the TodoList component.

It uses the useStoreState hook to get the state.

And he useStoreActions get the action we can use.

We pass in a value to add to set the payload parameter’s value.

Then in App , we wrap our app with the StoreProvider .

We pass in our store to it so we can get and set its states.

Then we put the TodoList inside it to let us get and set the state.

Conclusion

Conuse and Easy Peasy are both state management libraries we can use in our React app.

Categories
React Hooks

Top React Hooks — State and API

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.

Nice Hooks

Nice Hooks is a set of hooks that does various things.

To install it, we run:

npm install nice-hooks

The useLifeCycle hook lets us add lifecycle methods as we do with class components.

For instance, we can write:

import React from "react";
import { useLifeCycle } from "nice-hooks";

export default function App() {
  useLifeCycle({
    didMount() {
      console.log("mounted");
    },

    willUnmount() {
      console.log("willUnmount");
    },

    didUpdate() {
      console.log("didUpdate");
    },

    didMountAndWillUnmount: [
      {
        didMount() {
          console.log("didMount");
        },
        willUnmount() {
          console.log("willUnmount");
        }
      },
      {
        didMount() {
          console.log("didMount");
        },
        willUnmount() {
          console.log("willUnmount");
        }
      }
    ]
  });

  return <div />;
}

We use the useLifeCycle hook to add the lifecycle hooks to our components.

The useInstanceVar hook lets us create instance variables in our component.

For example, we can write:

import React from "react";
import { useInstanceVar, useSingleState } from "nice-hooks";

export default function App() {
  const [getIntervalVal, setIntervalVal] = useInstanceVar(null);
  const [state, setState] = useSingleState({ count: 0 });

  function start() {
    const interval = setInterval(
      () => setState({ count: state.count + 1 }),
      1000
    );
    setIntervalVal(interval);
  }

  function stop() {
    const interval = getIntervalVal();
    interval && clearInterval(interval);
  }

  return (
    <div>
      <p>{state.count}</p>
      <button onClick={start}>Start</button>
      <button onClick={stop}>Stop</button>
    </div>
  );
}

We use the useInstanceVar hook to create our getter and setter for our instance variable.

In the start function, we called setIntervalVal to set the instance variable value to the timer.

In the setInterval callback, we update the count state that’s returned from useSingleState .

In stop , we called getIntervalVal to get the state we set and call clearInterval on it if it’s set.

promise-hook

The promise-hook library lets us fetch data with a hook.

To install it, we install it by running:

yarn add promise-hook

or:

npm i promise-hook --save

Then we can use it by writing:

import React from "react";
import { usePromise } from "promise-hook";

const fetchName = () =>
  fetch(`https://api.agify.io/?name=michael`).then(res => res.json());

export default function App() {
  const { isLoading, data } = usePromise(fetchName, { resolve: true });

  return isLoading ? <div>Loading...</div> : <div>{JSON.stringify(data)}</div>;
}

We defined the fetchName function to get data from our app.

We passed that into the usePromise hook to get the data.

resolve means that we get data when the component mounts.

The isLoading state indicates whether data is loading or not.

data has the data.

We can pass arguments by writing:

import React from "react";
import { usePromise } from "promise-hook";

const fetchName = name =>
  fetch(`https://api.agify.io/?name=${name}`).then(res => res.json());

const Name = ({ name }) => {
  const { isLoading, data } = usePromise(() => fetchName(name), {
    resolve: true,
    resolveCondition: [name]
  });

  return isLoading ? <div>Loading...</div> : <div>{JSON.stringify(data)}</div>;
};

export default function App() {
  return <Name name="james" />;
}

We get the name prop and then pass that into the fetchName function.

resolveCondition has the value to watch for when the API is called.

Conclusion

Nice Hooks lets us manage state in various ways.

The promise-hook library lets us fetch data with a hook.