DEV Community

loading...
Cover image for React Custom Hooks - Sharing Logic Between Components

React Custom Hooks - Sharing Logic Between Components

aduranil profile image Lina Rudashevski ・2 min read

Below is an example of a React hook that is responsible for making a button turn purple in two different components. I use this is in my project which you can play here.

import { useState } from 'react';

 // hook code 
 function useMoveUpdate() {
  const [currentMove, setCurrentMove] = useState('');

   const newMove = (event) => {
    event.preventDefault();
    let move = event.currentTarget.value;
    let theVictim = null;
    if (event.currentTarget.value.includes('leave_comment')) {
      move = 'leave_comment';
      theVictim = event.currentTarget.id;
    }
    setCurrentMove(event.currentTarget.value);
  };

  return [currentMove, newMove];
}
import React from 'react';
import useMoveUpdate from '../hooks/CurrentMove';

function GameMoves({
  game, dispatch
}) {
  // component that uses the hook
  const [currentMove, newMove] = useMoveUpdate();

  return (
    <div>
      {['post_selfie', 'dont_post', 'go_live'].map(item => (
        <button
          className={currentMove === item ? 'button-color' : null}
          type="button"
          style={{ padding: '10px' }}
          value={item}
          onClick={newMove}
          disabled={!game.round_started}
        >
          {item.replace(/_/g, ' ')}
        </button>
      ))}
    </div>
  );
}

import React from 'react';
import { Phone } from '../images/iPhone';
import useMoveUpdate from '../hooks/CurrentMove';

function GameBox({ game, dispatch}) {
  // component that uses the hook
  const [currentMove, newMove] = useMoveUpdate();

  return (
    <div>
      <div style={{ display: 'flex', flexDirection: 'row' }}>
        {game.users.map(player => (
          <div style={{ margin: '1%' }} key={player.username}>
            {player.username}
            {!game.round_started && (player.started ? '!' : ' ?')}
            <div>
              {player.followers}
              {player.followers === 1 ? 'follower' : 'followers'}
            </div>
            <div style={{ marginBottom: '3px' }}>
              {player.stories}
              {player.stories === 1 ? 'story' : 'stories'}
            </div>
            <button
              onClick={newMove}
              id={player.id}
              disabled={!game.round_started}
              value={`leave_comment_${player.id}`}
              className={currentMove === `leave_comment_${player.id}` ? 'button-color' : null}
              type="button"
            >
              <Phone />
            </button>
            {' '}
          </div>
        ))}
      </div>
    </div>
  );
}

How it works.

const [currentMove, setCurrentMove] = useState('');

currentMove holds the value of which button should be purple and setCurrentMove executes the action, defined in the hook.

The state of the initial hook is an empty string, which means all of the buttons are green because the className is what changes when the button is clicked. The className dictates the CSS.

The hook returns [currentMove, newMove], and that is what useMoveUpdate returns in the components. Clicking the button executes newMove, the action that updates the button that is clicked and changes its color.

Here is an example of it working in my project:
Alt Text

Discussion

pic
Editor guide