4
\$\begingroup\$

I created a rough implementation of a component that lists stuff based on data has the option to enable searching for that data. I've not used React all that much so it's probably a terrible way to implement it. I looked into passing state upwards and the most common way I saw was to do what I did and pass the setter function as a prop. One thing that isn't clean is having to pass renderBans as a prop but I wasn't sure how else to render each item from the given data and update the state.

The list component

import Ban from './Ban'
import styles from '../styles/BansList.module.css'
import React, { useState, useEffect } from 'react';
import Search from './Search'
const BansList = ({title, bans, search=false}) => {
 const bansPerRender = 3;
 const [bansToRender, setBansToRender] = useState();
 const [next, setNext] = useState(3);
 const showMore = () => {
 setBansToRender(renderBans(bans.slice(0, next+bansPerRender)))
 setNext(next+bansPerRender)
 }
 const renderBans = bans => {
 let holdBans = []
 bans.map((ban, index) => {
 
 // convert from Unix timestamp to HH:MM:SS
 let banDate = new Date(ban.timestamp*1000)
 // if ban not expired
 if(new Date().getTime() < banDate.setMinutes(banDate.getMinutes() + ban.bantime))
 isExpired = false
 
 // reset banDate to original
 banDate = new Date(ban.timestamp * 1000)
 let permaBan;
 ban.bantime === 0 ? permaBan = true : permaBan = false; 
 holdBans.push(<Ban key={index} offenderName={ban.offender_name} offenderSteamId={ban.offender_steamid} banDate={banDate} adminName={ban.admin_name} banReason={ban.reason} banLength={ban.bantime} isExpired={false} permaBan={permaBan}/>)
 })
 return holdBans;
 }
 useEffect(() => {
 setBansToRender(renderBans(bans.slice(0, bansPerRender)))
 }, [])
 
 return (
 <>
 <div className={styles.wrapper}>
 {search && <Search toSearch={bans} sendResults={setBansToRender} renderFunc={renderBans} resultsToSend={bansPerRender}/>}
 <h1>{title}</h1>
 {bansToRender}
 <button onClick={() => {showMore()}}>Show More</button>
 </div>
 </>
 )
}
export default BansList; 

The search component

import React, { useState, useEffect, useContext } from 'react';
import Fuse from 'fuse.js'
import SearchResults from './SearchResults'
const Search = ({toSearch, sendResults, renderFunc, resultsToSend='all'}) => {
 // setup state for search
 const [query, setQuery] = useState("");
 const [searchResults, setSearchResults] = useState();
 let isExpired = true;
 const search = (query) => {
 if(!query) {
 setSearchResults(toSearch)
 return;
 }
 const fuseGuardban = new Fuse(toSearch, {
 keys: ["offender_name", "admin_name", "offender_steamid"],
 useExtendedSearch: true
 });
 const result = fuseGuardban.search(query)
 const matches = []
 if (!result.length) {
 setSearchResults([]);
 } else {
 result.forEach(({item}) => {
 matches.push(item);
 });
 setSearchResults(matches);
 }
 if(searchResults || searchResults == [])
 sendResults(renderFunc(searchResults.slice(0, resultsToSend)))
 }
 return (
 <>
 <input type="search" placeholder="Search by name" onChange={e => search(e.target.value)}/>
 <span>{query}</span>
 </>
 )
}
export default Search;
Sᴀᴍ Onᴇᴌᴀ
29.5k16 gold badges45 silver badges201 bronze badges
asked Jun 22, 2021 at 0:39
\$\endgroup\$

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.