React Machine Coding - rs-hash/Senior GitHub Wiki

1. STAR

import { useState } from "react";
import "./style.css";
const StarRating = ({ limit = 5, defaultRating = 2 }) => {
  const [rating, setRating] = useState(defaultRating);
  const handleRating = (e) => {
    setRating(Number(e.currentTarget.dataset.value));
  };
  return (
    <div>
      {[...new Array(limit).keys()].map((item, index) => (
        <span
          className={`star ${index < rating ? "rated" : ""}`}
          onClick={handleRating}
          data-value={index + 1}
          key={index}
        ></span>
      ))}
    </div>
  );
};

export default StarRating;


.star::before {
  content: "\2605";
  font-size: 35px;
  cursor: pointer;
}

.star.rated::before {
  content: "\2605";
  color: gold;
}

2. SEARCH

import { useState } from "react";

const Search = () => {
  const list = ["apple", "kiwi", "pineapple"];
  const [searchTerm, setSearchTerm] = useState("");
  const handleInputChange = (e) => {
    setSearchTerm(e.target.value);
  };

  const filteredItems = list.filter((item) =>
    item.toLowerCase().includes(searchTerm.toLowerCase())
  );
  return (
    <div>
      <input
        type="text"
        placeholder="Type to filter"
        onChange={handleInputChange}
      />
      <ul>
        {filteredItems.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>
    </div>
  );
};

export default Search;

Optimized Search

import { useState, useEffect } from "react";

const useDebounce = (value, delay) => {
  const [debouncedValue, setDebouncedValue] = useState(value);
  useEffect(() => {
    const timer = setTimeout(() => {
      setDebouncedValue(value);
    }, delay);

    return () => {
      clearTimeout(timer);
    };
  }, [value, delay]);

  return debouncedValue;
};

export default useDebounce;


import { useState, useMemo } from "react";
import useDebounce from "./useDebounce";

const Search = () => {
  const list = ["apple", "kiwi", "pineapple"];
  const [searchTerm, setSearchTerm] = useState("");
  const debouncedSearchTerm = useDebounce(searchTerm, 300);
  const handleInputChange = (e) => {
    setSearchTerm(e.target.value);
  };

  const filteredItems = useMemo(
    () =>
      list.filter((item) => {
        console.log("calling filter");
        return item.toLowerCase().includes(searchTerm.toLowerCase());
      }),
    [debouncedSearchTerm]
  );
  return (
    <div>
      <input
        type="text"
        placeholder="Type to filter"
        onChange={handleInputChange}
      />
      <ul>
        {filteredItems.map((item, index) => (
          <li key={index}>{item}</li>
        ))}
      </ul>

      <button onClick={() => console.log("done")}>Click</button>
    </div>
  );
};

export default Search;

3. Image Carousel

import { useState, useEffect } from "react";

const ImageCarousel = () => {
 const [images, setImages] = useState([]);
  const [currentImage, setCurrentImage] = useState(0);

  useEffect(() => {
    fetchImages();
    const timer = setTimeout(() => {
      handleNextClick();
    }, 2000);

    return () => {
      clearTimeout(timer);
    };
  }, [currentImage]);

  const fetchImages = async () => {
    try {
      const data = await fetch("https://picsum.photos/v2/list?page=2&limit=10");
      const response = await data.json();
      setImages(response);
    } catch (e) {
      console.error(e);
    }
  };

  const handlePrevClick = () => {
    if (currentImage !== 0) setCurrentImage((currentImage) => currentImage - 1);
    else setCurrentImage(images.length - 1);
  };
  const handleNextClick = () => {
    if (currentImage !== images.length - 1)
      setCurrentImage((currentImage) => currentImage + 1);
    else setCurrentImage(0);
  };

  return (
    <div style={{ display: "flex" }}>
      <button onClick={handlePrevClick}>PREV</button>
      {images.length > 0 && (
        <img
          src={images[currentImage].download_url}
          height="400"
          width="500"
          style={{ margin: "20px" }}
        />
      )}

      <button onClick={handleNextClick}>NEXT</button>
    </div>
  );
}
export default ImageCarousel;

4. Table

import { useState, useEffect } from "react";

const Table = () => {
  const [userData, setUserData] = useState([]);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);

  useEffect(() => {
    const fetchUserData = async () => {
      try {
        const response = await fetch("https://dummyjson.com/users");
        if (!response.ok) {
          throw new Error("Network response was not ok");
        }
        const data = await response.json();
        const sortedData = data.users.sort((a, b) =>
          a.firstName.localeCompare(b.firstName)
        );
        setUserData(sortedData);
      } catch (error) {
        setError(error.message);
      } finally {
        setLoading(false);
      }
    };

    fetchUserData();
  }, []);

  if (loading) {
    return <p>Loading...</p>;
  }

  if (error) {
    return <p>Error: {error}</p>;
  }

  return (
    <div>
      <h2>Table</h2>
      <table>
        <thead>
          <tr>
            <th>Name</th>
            <th>Email</th>
          </tr>
        </thead>
        <tbody>
          {userData.map((user) => (
            <tr key={user.id}>
              <td>{user.firstName} {user.lastName}</td>
              <td>{user.email}</td>
            </tr>
          ))}
        </tbody>
      </table>
    </div>
  );
};

export default Table;

5. StopWatch

import { useState, useEffect } from "react";

const Stopwatch = () => {
  const [seconds, setSeconds] = useState(5000);
  const [isActive, setIsActive] = useState(true);

  useEffect(() => {
    let timer;
    if (isActive) {
      timer = setInterval(() => {
        setSeconds((seconds) => {
          if (seconds > 0) {
            return seconds - 1;
          } else {
            setIsActive(false);
            return 0;
          }
        });
      }, 1000);
    }
    return () => {
      clearInterval(timer);
    };
  }, [isActive]);

  const handleStart = () => {
    setIsActive(true);
    setSeconds(5000);
  };

  const handlePause = () => {
    setIsActive((isActive) => !isActive);
  };

  const handleStop = () => {
    setIsActive(false);
    setSeconds(0);
  };

  const formatTime = () => {
    const hours = Math.floor(seconds / 3600);
    const minutes = Math.floor((seconds % 3600) / 60);
    const sec = Math.floor(seconds % 60);

    const paddedHours = String(hours).padStart(2, "0");
    const paddedMinutes = String(minutes).padStart(2, "0");
    const paddedSeconds = String(sec).padStart(2, "0");

    return `${paddedHours} hour : ${paddedMinutes} minutes : ${paddedSeconds} seconds`;
  };
  return (
    <div>
      <h2> Stop Watch </h2>
      <h4>{formatTime()}</h4>
      <div style={{ display: "flex" }}>
        <button onClick={handleStart}>Start</button>
        <button onClick={handlePause}>{isActive ? "Pause" : "Resume"}</button>
        <button onClick={handleStop}>Stop</button>
      </div>
    </div>
  );
};

export default Stopwatch;

6. Todos

import { useState } from "react";
import './Todo.css'; // Assume you have a Todo.css file for styles

const Todo = () => {
  const [todos, setTodos] = useState(["todo1", "todo2", "todo3"]);
  const [text, setText] = useState("");

  const addTodo = () => {
    if (text.trim() && !todos.includes(text.trim())) {
      setTodos((prevTodos) => [...prevTodos, text.trim()]);
      setText("");
    }
  };

  const deleteTodo = (todoToDelete) => {
    setTodos((prevTodos) => prevTodos.filter((todo) => todo !== todoToDelete));
  };

  const handleKeyDown = (e) => {
    if (e.key === "Enter") addTodo();
  };

  return (
    <div className="todo-container">
      <h2>Todos</h2>
      <div className="todo-input-container">
        <input
          type="text"
          value={text}
          onChange={(e) => setText(e.target.value)}
          onKeyDown={handleKeyDown}
          placeholder="Type your Todo"
          aria-label="New todo"
        />
        <button onClick={addTodo}>Add Task</button>
      </div>
      <ul className="todo-list">
        {todos.map((todo) => (
          <li key={todo} className="todo-item">
            {todo}
            <button
              onClick={() => deleteTodo(todo)}
              className="todo-delete-button"
              aria-label={`Delete ${todo}`}
            >
              X
            </button>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default Todo;

7. FOLDER

<Folder data={folderData[0]} />

import { useState } from "react";

const Folder = ({ data }) => {
  const [isExpanded, setIsExpanded] = useState(true);
  return (
    <>
      {data.children?.length > 0 ? (
        <>
          <p
            onClick={() => setIsExpanded(!isExpanded)}
            style={{
              textAlign: "left",
              cursor: "pointer",
            }}
          >
            {data.name}
          </p>

          {isExpanded && (
            <div style={{ marginLeft: "20px" }}>
              {data.children.map((item) => (
                <Folder data={item}></Folder>
              ))}
            </div>
          )}
        </>
      ) : (
        <p style={{ textAlign: "left", paddingLeft: "45px" }}>{data.name}</p>
      )}
    </>
  );
};

export default Folder;

8. INFINITE SCROLL

import { useState, useEffect } from "react";

const InfiniteScroll = () => {
  const [data, setData] = useState([]);
  const [page, setPage] = useState(1); // Start with page 1 for the first fetch
  const [loading, setLoading] = useState(false);

  useEffect(() => {
    const handleScroll = () => {
      if (
        window.innerHeight + document.documentElement.scrollTop + 4 >=
        document.documentElement.scrollHeight
      ) {
        // Only fetch new data if not already loading
        if (!loading) {
          setLoading(true);
          setPage((prevPage) => prevPage + 1);
        }
      }
    };

    // Add scroll event listener
    window.addEventListener("scroll", handleScroll);

    // Cleanup event listener on component unmount
    return () => {
      window.removeEventListener("scroll", handleScroll);
    };
  }, [loading]); // Depend on loading to control when to fetch

  useEffect(() => {
    // Fetch data whenever page changes
    const fetchData = async () => {
      try {
        const response = await fetch(
          `https://jsonplaceholder.typicode.com/posts?_limit=10&_page=${page}`
        );
        const newData = await response.json();
        setData((prevData) => [...prevData, ...newData]);
      } catch (e) {
        console.error(e);
      } finally {
        setLoading(false);
      }
    };

    fetchData();
  }, [page]); // Depend on page to trigger data fetching

  return (
    <div>
      {data.map((item) => (
        <div key={item.id}>
          <h2>{item.title}</h2>
          <p>{item.body}</p>
        </div>
      ))}
      {loading && <p>Loading...</p>} {/* Show loading indicator */}
    </div>
  );
};

export default InfiniteScroll;

9. ACCORDION

import { useState } from "react";
import data from "./data";
import "./styles.css";

export default function Accordian() {
  const [selected, setSelected] = useState(null);
  const [enableMultiSelection, setEnableMultiSelection] = useState(false);
  const [multiple, setMultiple] = useState([]);

  function handleSingleSelection(getCurrentId) {
    setSelected(getCurrentId === selected ? null : getCurrentId);
  }

  function handleMultiSelection(getCurrentId) {
    let cpyMutiple = [...multiple];
    const findIndexOfCurrentId = cpyMutiple.indexOf(getCurrentId);

    console.log(findIndexOfCurrentId);
    if (findIndexOfCurrentId === -1) cpyMutiple.push(getCurrentId);
    else cpyMutiple.splice(findIndexOfCurrentId, 1);

    setMultiple(cpyMutiple);
  }

  console.log(selected, multiple);
  return (
    <div className="acc-wrapper">
      <button onClick={() => setEnableMultiSelection(!enableMultiSelection)}>
        Enable Multi Selection
      </button>
      <div className="accordian">
        {data && data.length > 0 ? (
          data.map((dataItem) => (
            <div className="item">
              <div
                onClick={
                  enableMultiSelection
                    ? () => handleMultiSelection(dataItem.id)
                    : () => handleSingleSelection(dataItem.id)
                }
                className="title"
              >
                <h3>{dataItem.question}</h3>
                <span>+</span>
              </div>
              {enableMultiSelection
                ? multiple.indexOf(dataItem.id) !== -1 && (
                    <div className="acc-content ">{dataItem.answer}</div>
                  )
                : selected === dataItem.id && (
                    <div className="acc-content ">{dataItem.answer}</div>
                  )}
              {/* {selected === dataItem.id ||
              multiple.indexOf(dataItem.id) !== -1 ? (
                <div className="content">{dataItem.answer}</div>
              ) : null} */}
            </div>
          ))
        ) : (
          <div>No data found !</div>
        )}
      </div>
    </div>
  );
}

10. Modal

import { useState } from "react";
import "./style.css";

// Main Modal Component
const Modal = () => {
  const [showModal, setShowModal] = useState(false);

  const handleOpen = () => {
    setShowModal(true);
  };

  const handleClose = () => {
    setShowModal(false);
  };

  return (
    <>
      <button onClick={handleOpen}>Show Modal</button>
      <RenderModal
        showModal={showModal}
        handleClose={handleClose}
      >
        <h2>Modal Title</h2>
        <p>Modal content</p>
      </RenderModal>
    </>
  );
};

// RenderModal Component
const RenderModal = ({ children, showModal, handleClose }) => {
  if (!showModal) return null;

  return (
    <div className="modal-overlay">
      <div className="modal-content">
        <button onClick={handleClose}>X</button>
        {children}
      </div>
    </div>
  );
};

export default Modal;


/* style.css */
.modal-overlay {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  bottom: 0;
  background: rgba(0, 0, 0, 0.5);
  display: flex;
  align-items: center;
  justify-content: center;
}

.modal-content {
  background: white;
  padding: 20px;
  border-radius: 8px;
  width: 400px;
  position: relative;
}

button {
  cursor: pointer;
  background-color: #007bff;
  color: white;
  border: none;
  padding: 10px;
  border-radius: 5px;
  margin: 5px;
}

button:hover {
  background-color: #0056b3;
}

11. Form

import React, { useState } from 'react';

const FormComponent = () => {
  const [formData, setFormData] = useState({
    text: '',
    password: '',
    textarea: '',
    checkbox: false,
    radio: '',
    select: '',
    number: '',
    date: '',
    file: null,
    range: 50,
  });

  const handleChange = (e) => {
    const { name, value, type, checked, files } = e.target;
    setFormData((prevData) => ({
      ...prevData,
      [name]: type === 'checkbox' ? checked : type === 'file' ? files[0] : value,
    }));
  };

  const handleSubmit = (e) => {
    e.preventDefault();
    console.log('Form Data Submitted:', formData);
    // Handle form data submission here, e.g., sending it to an API
  };

  return (
    <form onSubmit={handleSubmit}>
      <div>
        <label>
          Text:
          <input
            type="text"
            name="text"
            value={formData.text}
            onChange={handleChange}
          />
        </label>
      </div>
      <div>
        <label>
          Password:
          <input
            type="password"
            name="password"
            value={formData.password}
            onChange={handleChange}
          />
        </label>
      </div>
      <div>
        <label>
          Text Area:
          <textarea
            name="textarea"
            value={formData.textarea}
            onChange={handleChange}
          />
        </label>
      </div>
      <div>
        <label>
          Checkbox:
          <input
            type="checkbox"
            name="checkbox"
            checked={formData.checkbox}
            onChange={handleChange}
          />
        </label>
      </div>
      <div>
        <label>
          Radio Option 1:
          <input
            type="radio"
            name="radio"
            value="option1"
            checked={formData.radio === 'option1'}
            onChange={handleChange}
          />
        </label>
        <label>
          Radio Option 2:
          <input
            type="radio"
            name="radio"
            value="option2"
            checked={formData.radio === 'option2'}
            onChange={handleChange}
          />
        </label>
      </div>
      <div>
        <label>
          Select:
          <select
            name="select"
            value={formData.select}
            onChange={handleChange}
          >
            <option value="">Select an option</option>
            <option value="option1">Option 1</option>
            <option value="option2">Option 2</option>
          </select>
        </label>
      </div>
      <div>
        <label>
          Number:
          <input
            type="number"
            name="number"
            value={formData.number}
            onChange={handleChange}
          />
        </label>
      </div>
      <div>
        <label>
          Date:
          <input
            type="date"
            name="date"
            value={formData.date}
            onChange={handleChange}
          />
        </label>
      </div>
      <div>
        <label>
          File:
          <input
            type="file"
            name="file"
            onChange={handleChange}
          />
        </label>
      </div>
      <div>
        <label>
          Range:
          <input
            type="range"
            name="range"
            min="0"
            max="100"
            value={formData.range}
            onChange={handleChange}
          />
        </label>
      </div>
      <div>
        <button type="submit">Submit</button>
        <button type="reset" onClick={() => setFormData({
          text: '',
          password: '',
          textarea: '',
          checkbox: false,
          radio: '',
          select: '',
          number: '',
          date: '',
          file: null,
          range: 50,
        })}>
          Reset
        </button>
      </div>
    </form>
  );
};

export default FormComponent;

12. API

import React, { useState } from 'react';

const ApiComponent = () => {
  const [data, setData] = useState(null);
  const [postData, setPostData] = useState({ name: '', age: '' });
  const [putData, setPutData] = useState({ name: '', age: '' });

  // Function to handle GET request
  const fetchData = async () => {
    try {
      const response = await fetch('https://jsonplaceholder.typicode.com/users');
      const result = await response.json();
      setData(result);
    } catch (error) {
      console.error('Error fetching data:', error);
    }
  };

  // Function to handle POST request
  const postDataHandler = async () => {
    try {
      const response = await fetch('https://jsonplaceholder.typicode.com/users', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(postData),
      });
      const result = await response.json();
      console.log('POST response:', result);
    } catch (error) {
      console.error('Error posting data:', error);
    }
  };

  // Function to handle PUT request
  const putDataHandler = async () => {
    try {
      const response = await fetch('https://jsonplaceholder.typicode.com/users/1', {
        method: 'PUT',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(putData),
      });
      const result = await response.json();
      console.log('PUT response:', result);
    } catch (error) {
      console.error('Error updating data:', error);
    }
  };

  // Function to handle DELETE request
  const deleteDataHandler = async () => {
    try {
      const response = await fetch('https://jsonplaceholder.typicode.com/users/1', {
        method: 'DELETE',
      });
      if (response.ok) {
        console.log('DELETE request successful');
      } else {
        console.error('Error deleting data:', response.statusText);
      }
    } catch (error) {
      console.error('Error deleting data:', error);
    }
  };

  return (
    <div>
      <h1>Fetch API Examples</h1>
      <button onClick={fetchData}>Fetch Data (GET)</button>
      <button onClick={postDataHandler}>Post Data (POST)</button>
      <button onClick={putDataHandler}>Update Data (PUT)</button>
      <button onClick={deleteDataHandler}>Delete Data (DELETE)</button>

      {data && (
        <ul>
          {data.map((item) => (
            <li key={item.id}>{item.name}</li>
          ))}
        </ul>
      )}
    </div>
  );
};

export default ApiComponent;
⚠️ **GitHub.com Fallback** ⚠️