steeleye / recruitment-ext

13 stars 25 forks source link

Satyam_Kumar_FrontEnd #196

Open Satyam8804 opened 1 year ago

Satyam8804 commented 1 year ago

Live Deployment Link : https://steel-eye-assignment.vercel.app/

Q1 . Explain what the simple List component does

The List component is a basic React component that displays a list of clickable items based on an array of items passed as a prop. It uses a memoized SingleListItem component to render each item and handles click events. The selected item is tracked using a state variable and reset when the list of items changes. Prop types are defined using PropTypes, and the component is optimized for performance using memoization.

Q2. What problems / warnings are there with code?

  1. The use of useState in the provided code is incorrect. The correct syntax for using useState hook is:

    const [selectedIndex, setSelectedIndex] = useState( );

    where selectedIndex is the state variable that holds the current value, and setSelectedIndex is the function that can be used to update the value of selectedIndex state variable.

  2. 'Key' props is missing in "SingleListItem " while rendering an array of components with unique items. You can add a key prop to the SingleListItem component and set it to a unique value, such as the index prop, to address this issue.

 <ul style={{ textAlign: 'left' }}>
      {items.map((item, index) => (
        <SingleListItem
          key={index}
          onClickHandler={() => handleClick(index)}
          text={item.text}
          index={index}
          isSelected={index === selectedIndex }
        />
      ))}
    </ul>

and in the same piece of code , isSelected is a boolean but we are assigning "index" value to it which is a number . To fix this code i modified it to
isSelected={index === selectedIndex }

This code is setting the "isSelected" prop to a boolean value that indicates whether the current item is selected or not. It does this by checking if the index of the current item being mapped over is equal to the value of selectedIndex.

  1. The use of PropTypes in the " items" propType validation is incorrect. The correct syntax for validating an array of objects with a specific shape using PropTypes is:
   items: PropTypes.arrayOf(
  PropTypes.shape({
    text: PropTypes.string.isRequired,
  })
)

This validates that the items prop is an array of objects, where each object has a text property of type string that is required (i.e., must be present).

  1. The "isSelected " prop is intended to be a boolean value, indicating whether an item is selected or not. setting it to null may not be a valid boolean value, and it can lead to unexpected results in the rendering of the SingleListItem component. To fix this, you can set a valid boolean value for " isSelected " prop, such as "false" or "0", instead of "null",
useEffect(() => {
    setSelectedIndex(0);
  }, [items]);
  1. "isSelected" is expected to be a boolean value but here it is defined as "PropType.bool" , which do not enforce boolean type. To fix this issue we need to add "isRequired" so that it must be a requires boolean value
  WrappedSingleListItem.propTypes = {
  index: PropTypes.number,
  isSelected: PropTypes.bool.isRequired,
  onClickHandler: PropTypes.func.isRequired,
  text: PropTypes.string.isRequired,
};

6 . "onClick={onClickHandler(index)}" would not work as expected because it would immediately invoke the " onClickHandler" function with the index parameter when the component renders, rather than waiting for the actual click event to occur. for example

![Screenshot 2023-04-23 172144](https://user-images.githubusercontent.com/88649908/233838101- 
 26fc6c10-a226-4503-9ebf-5562ca5bc27e.png)

To fix this issue :

      onClick={() => onClickHandler(index)}

Q3. Please fix, optimize, and/or modify the component as much as you think is necessary.


import React, { useState, useEffect, memo } from 'react';
import PropTypes from 'prop-types';

// Single List Item
const WrappedSingleListItem = ({
  index,
  isSelected,
  onClickHandler,
  text,
}) => {
  return (
    <li className='li'
      style={{ backgroundColor: isSelected ? 'green' : 'red'}}
      onClick={()=>onClickHandler(index)}
    >
      {text}
    </li>
  );
};

WrappedSingleListItem.propTypes = {
  index: PropTypes.number,
  isSelected: PropTypes.bool.isRequired,
  onClickHandler: PropTypes.func.isRequired,
  text: PropTypes.string.isRequired,
};

const SingleListItem = memo(WrappedSingleListItem);

// List Component
const WrappedListComponent = ({
  items,
}) => {

  const [selectedIndex ,setSelectedIndex] = useState();

  useEffect(() => {
    setSelectedIndex(4);
  }, [items])

  const handleClick = index => {
    console.log(index)
    setSelectedIndex(index);

  };

  return (
    <>
    <ul style={{ textAlign: 'left' }}>
       Rate My Answers ! 
      { items && items.map((item, index) => (
        <SingleListItem
          key={index}
          onClickHandler={() => handleClick(index)}
          text={item.text}
          index={index}
          isSelected={index === selectedIndex}
        />
      ))}
    </ul>
    </>
  )
};

WrappedListComponent.propTypes = {
  items: PropTypes.arrayOf(PropTypes.shape({

    text: PropTypes.string.isRequired,

  })),
};

WrappedListComponent.defaultProps = {
  items:
  [
    { text: "0"},
    { text: "1"},
    {text:"2"},
    {text:"3"},
    {text :"4"},
    ],
};

const List2 = memo(WrappedListComponent);

export default List2;

CSS

.li{
  text-align: center;
  display: flex;
  align-items: center;
  justify-content: center;
  list-style: none;
  cursor: pointer;
  color: white;
  padding: 1rem;
  border-radius: 5px;
  font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif;
}
.li:hover{
  transform: scale(1.1);
}

ul{
  display: flex;
  gap: 1rem;
  background-color: rgba(0, 128, 0, 0.26);
  border-radius: 10px;
  width: max-content;
  font-family: 'Lucida Sans', 'Lucida Sans Regular', 'Lucida Grande', 'Lucida Sans Unicode', Geneva, Verdana, sans-serif;
  font-weight: 700;
  color: gray;
  padding: 2rem;
  flex-direction: column;
}

body{
  display: flex;
  justify-content: center;
  align-items: center;
}