Languages
[Edit]
EN

React - sticky reactions component

0 points
Created by:
cory
346

In this article, we would like to show you how to create a custom sticky reactions component in React.

// ONLINE-RUNNER:browser;

// Note: Uncomment import lines during working with JSX Compiler.
// import React from 'react';
// import ReactDOM from 'react-dom';

const reactionsStyle = {
    margin: '20px 0px',
  	position: 'sticky',
    top: '60px',
  	width: '36px',
};

const iconStyle = {
    margin: '16px 8px',
  	background: 'white',
    width: '20px',
  	height: '20px',
  	display: 'block',
  	cursor: 'pointer'
};

const defaultIconStyle = {
    ...iconStyle,
  	color: 'silver'
};

const selectedIconStyle = {
    ...iconStyle,
  	color: 'blue'
};

const LikeIcon = (props) => (
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512" {...props}>
    <g fill="currentColor">
      <path d="M466.27 286.69C475.04 271.84 480 256 480 236.85c0-44.015-37.218-85.58-85.82-85.58H357.7c4.92-12.81 8.85-28.13 8.85-46.54C366.55 31.936 328.86 0 271.28 0c-61.607 0-58.093 94.933-71.76 108.6-22.747 22.747-49.615 66.447-68.76 83.4H32c-17.673 0-32 14.327-32 32v240c0 17.673 14.327 32 32 32h64c14.893 0 27.408-10.174 30.978-23.95 44.509 1.001 75.06 39.94 177.802 39.94 7.22 0 15.22.01 22.22.01 77.117 0 111.986-39.423 112.94-95.33 13.319-18.425 20.299-43.122 17.34-66.99 9.854-18.452 13.664-40.343 8.99-62.99zm-61.75 53.83c12.56 21.13 1.26 49.41-13.94 57.57 7.7 48.78-17.608 65.9-53.12 65.9h-37.82c-71.639 0-118.029-37.82-171.64-37.82V240h10.92c28.36 0 67.98-70.89 94.54-97.46 28.36-28.36 18.91-75.63 37.82-94.54 47.27 0 47.27 32.98 47.27 56.73 0 39.17-28.36 56.72-28.36 94.54h103.99c21.11 0 37.73 18.91 37.82 37.82.09 18.9-12.82 37.81-22.27 37.81 13.489 14.555 16.371 45.236-5.21 65.62zM88 432c0 13.255-10.745 24-24 24s-24-10.745-24-24 10.745-24 24-24 24 10.745 24 24z" />
    </g>
  </svg>
);

const StarIcon = (props) => (
  <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512" {...props}>
    <g fill="currentColor">
      <path fill="currentColor" d="M528.1 171.5L382 150.2 316.7 17.8c-11.7-23.6-45.6-23.9-57.4 0L194 150.2 47.9 171.5c-26.2 3.8-36.7 36.1-17.7 54.6l105.7 103-25 145.5c-4.5 26.3 23.2 46 46.4 33.7L288 439.6l130.7 68.7c23.2 12.2 50.9-7.4 46.4-33.7l-25-145.5 105.7-103c19-18.5 8.5-50.8-17.7-54.6zM388.6 312.3l23.7 138.4L288 385.4l-124.3 65.3 23.7-138.4-100.6-98 139-20.2 62.2-126 62.2 126 139 20.2-100.6 98z" />
    </g>
  </svg>
);

const Reactions = ({ reactions, onClick }) => {
  	const [state, setState] = React.useState(() => (reactions ?? {})); // only to store state locally
  	React.useEffect(() => setState(reactions ?? {}), [reactions]);     // only to store state locally
  	const createHandleClick = (name) => {
      	return () => {
            const checked = !state[name];
            setState({ ...state, [name]: checked });
            if (onClick) {
                onClick(name, checked);
            }
        };
    };
	return (
      <div style={reactionsStyle}>
        <LikeIcon
          style={state.like ? selectedIconStyle : defaultIconStyle}
          onClick={createHandleClick('like')}
        />
        <StarIcon
          style={state.star ? selectedIconStyle : defaultIconStyle}
          onClick={createHandleClick('star')}
        />
      </div>
    );
};

// Usage example:

const bannerStyle = {
	height: '150px',
  	background: 'gold'
};

const pageStyle = {
	margin: '10px auto',
  	maxWidth: '500px',
  	display: 'flex'
};

const textStyle = {
  	margin: '0 0 0 20px',
  	background: '#f1f1f1',
	flex: '1'
};

const App = () => {
  	const [reactions, setReactions] = React.useState({});
  	const handleReactionClick = (name, checked) => {
    	console.log(`${name} is ${checked ? 'checked' : 'unchecked'}`);
      	//TODO: request to backend
      	setReactions({ ...reactions, [name]: checked });
    };
    return (
      <>
        <div style={bannerStyle}>
        	Some banner here ...
        </div>
		<div style={pageStyle}>
          <div>
          	<Reactions reactions={reactions} onClick={handleReactionClick} />
          </div>
          <div style={textStyle}>
            {Array(50).fill().map((v, i) => <div key={i}>Some text here ...</div>)}
          </div>
        </div>
      </>
    );
}

const root = document.querySelector('#root');
ReactDOM.render(<App />, root);
Native Advertising
🚀
Get your tech brand or product in front of software developers.
For more information Contact us
Dirask - we help you to
solve coding problems.
Ask question.

❤️💻 🙂

Join