I did a little bit of research but I found old examples with usually Redux or with one main component and cannot figure out the logic.
I can get data from an API but I do need to search, sort, filter, etc on that data (even at the same time). I know that I should not mutate the state directly, so in this case, I will have a couple of different state sets such as filteredData, sortedData, etc. However, which state am I going to pass to the Player component? How will sorting functionality will work on filtered data? I am extremely confused.
I would like to put my state and state-related logic in a Context but if this seems problematic or wrong, then I can try your approach.
Context
const ContextProvider = ({ children }) => {
const [data, setData] = useState([]);
const [filteredData, setFilteredData] = useState([]);
const [sortedData, setSortedData] = useState([]);
useEffect(() => {
fetch('URL HERE')
.then(data => data.json())
.then(data=> setData(data));
}, []);
const handleSearch = e => {
let value = e.target.value;
const filteredData = data.filter(player=>
player.name.includes(value)
);
setFilteredData(filteredData);
};
const handleSort = e => {
let value = e.target.value;
// I am trying to sort FILTERED DATA?
const sortedData = filteredData.sort((a, b) => {
if (a[value] < b[value]) {
return 1;
} else {
return -1;
}
});
setSortedData(sortedData);
};
return (
<Context.Provider
value={{ data, handleSearch, handleSort, filteredData, sortedData}}
>
{children}
</Context.Provider>
);
};
Search
const Search = () => {
const { handleSearch, handleSort } = useContext(Context);
return (
<div className='row'>
<Input
type='search'
name='search'
onChange={handleSearch}
></Input>
<Input
type='select'
name='select'
onChange={handleSort}
>
<option value='name'>Name</option>
<option value='team'>Team</option>
</Input>
</div>
);
};
Player
const Player = () => {
const {data, filteredData, sortedData} = useContext(Context);
return (
<ul>
//{data or filteredData or sortedData will be mapped?}
<li>// not sure what to do</li>
</ul>
);
};
I really appreciate code examples with some explanation.
There are many ways you can do this.
My suggestion would be:-
const [filteredData, setFilteredData] = useState(data) (this will not work). So do useEffect() to update filteredData in Player then:-useEffect(() => {
setFilteredData(data)
}, [])
setFilteredData()inputs, then return filteredData which contain dafault datasearch input, then do filtering search on filteredData (using setFilteredData())sort input, then do sorting on filteredData (using setFilteredData())search and sort inputs, then do both action on filteredData (using setFilteredData())Player, you can just return filteredDataconst ContextProvider = ({ children }) => {
const [data, setData] = useState([]);
const [filteredData, setFilteredData] = useState([]);
const [searchKey, setSearchKey] = useState('');
const [sortKey, setSortKey] = useState([]);
useEffect(() => {
fetch('URL HERE')
.then(data => data.json())
.then(data=> setData(data));
}, []);
const handleSearch = () => {
const filteredData = filteredData.filter(player=>
player.name.includes(searchKey)
);
setFilteredData(filteredData);
};
const handleSort = () => {
const sortedData = filteredData.sort((a, b) => {
if (a[sortKey] < b[sortKey]) {
return 1;
} else {
return -1;
}
});
setFilteredData(sortedData);
};
return (
<Context.Provider
value={{
data, filteredData, searchKey, sortKey,
setFilteredData, setSearchKey, setSortKey,
handleSearch,
handleSort,
}}
>
{children}
</Context.Provider>
);
};
const Search = () => {
const {
searchKey, setSearchKey,
sortKey, setSortKey
} = useContext(Context);
return (
<div className='row'>
<Input
type='search'
name='search'
value={searchKey}
onChange={e => setSearchKey(e.target.value)}
></Input>
<Input
type='select'
name='select'
value={sortKey}
onChange={e => setSortKey(e.target.value)}
>
<option value='name'>Name</option>
<option value='team'>Team</option>
</Input>
</div>
);
};
const Player = () => {
const {
data,
filteredData, setFilteredData,
searchKey, sortKey.
handleSearch, handleSort
} = useContext(Context);
// set filteredData
useEffect(() => {
setFIlteredData(data)
}, []) // should run once on mounted
// do search
// should be dependent on search input state (so you need a state to hold value need for searching)
useEffect(() => {
handleSearch()
}, [searchKey]) // will only fired/run if searchState changes
// do sorting
// should be dependent on sorting input state (so you need a state to hold value need for sorting)
useEffect(() => {
handleSort()
}, [sortKey]) // will only fired/run if sortingState changes
return (
<ul>
{filteredData.map(data => (
{/* display data info */}
))}
</ul>
);
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With