This is a solution to the Manage landing page challenge on Frontend Mentor. Frontend Mentor challenges help you improve your coding skills by building realistic projects.
Note: Delete this note and update the table of contents based on what sections you keep.
Users should be able to:
- View the optimal layout for the site depending on their device's screen size
- See hover states for all interactive elements on the page
- See all testimonials in a horizontal slider
- Receive an error message when the newsletter sign up
form
is submitted if:- The
input
field is empty - The email address is not formatted correctly
- The
- Semantic HTML5 markup
- CSS custom properties
- Flexbox
- CSS Grid
- Mobile-first workflow
- React - JS library
- ReactRouter - Allows to add routing to the React app
- eslint and prettier
This exercise was for me to learn some React basics and reinforce some of the knowledge I had before. I have learned class components, though I preferred to use function components with hooks like useState
, useEffect
, useRef
, useMemo
, forwardRef
, useContext
and so on.
// get and update width and gap
useEffect(() => {
setSlideData({
width: props.slideRef.current !== undefined ? props.slideRef.current.clientWidth : 0,
gap: parseInt(
window.getComputedStyle(containerRef.current).getPropertyValue('column-gap')
)
});
}, [props.slideRef, isMobile]);
const Opinion = forwardRef((props, ref) => {
return (
<div className={props.className} id={props.id} ref={ref}>
<img className="avatar" src={props.avatar} alt="avatar" />
<h3>{props.fullName}</h3>
<blockquote>{props.children}</blockquote>
</div>
);
});
Opinion.displayName = 'Slideshow-slide';
// get and update width and gap
function useSlide() {
const [slideData, setSlideData] = useState({ width: 0, gap: 0 });
useEffect(() => {
const update = debounce(() => {
setSlideData({
width: props.slideRef.current?.clientWidth || 0,
gap: parseInt(
window.getComputedStyle(containerRef.current).getPropertyValue('column-gap')
)
});
}, 200);
window.addEventListener('resize', update);
update();
return () => window.removeEventListener('resize', update);
}, [props.slideRef.current]);
return slideData;
}
Used context
too, but later on found it obsolete
The hardest component was possibly the Slideshow, as it was the most interactive part of the page. Code here
Side effect of working on this website was also learning about eslint
, prettier
and integrating them together with React
and VS Code
as external files.
I've added React Router, but... I didn't feel the need to work on the subpages. Basically there is nothing on them for now. I have some upcoming next projects and another technologies to learn.
So the next fun project would be a vegan shopping website for - a client! No longer creating for my own sake. This time I'm going to use TypeScript to understand it better than just the basics. For the next projects I'm looking forward to using some React framework - Gatsby. This challenge is looking good too.