0

i want the players to be shown based on the year that the user selects. for example if i choose 2011 in the 1st select at the 2nd select show only the players that are born in 2011. i created a if statement for every year and checked if he is born between 1st January of that year and 31 December, but i dont think thats too efficient to do (100 if statements). im working with React js

The code is below

import React, { useState, useEffect } from 'react';
import './style.css';

export default function App() {
  const vitet = [
    2030, 2029, 2028, 2027, 2026, 2025, 2024, 2023, 2022, 2021, 2020, 2019,
    2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009, 2008, 2007,
    2006, 2005, 2004, 2003, 2002, 2001, 2000, 1999, 1998, 1997, 1996, 1995,
    1994, 1993, 1992, 1991, 1990, 1989, 1988, 1987, 1986, 1985, 1984, 1983,
    1982, 1981, 1980, 1979, 1978, 1977, 1976, 1975, 1974, 1973, 1972, 1971,
    1970, 1969, 1968, 1967, 1966, 1965, 1964, 1963, 1962, 1961, 1960, 1959,
    1958, 1957, 1956, 1955, 1954, 1953, 1952, 1951, 1950, 1949, 1948, 1947,
    1946, 1945, 1944, 1943, 1942, 1941, 1940, 1939, 1938, 1937, 1936, 1935,
    1934, 1933, 1932, 1931, 1930, 1929, 1928, 1927, 1926, 1925, 1924, 1923,
    1922, 1921, 1920, 1919, 1918, 1917, 1916, 1915, 1914, 1913, 1912, 1911,
  ];

  const [year, setyear] = useState('');
  const [option, setOption] = useState([]);
  const [players, setPlayers] = useState([
    { playerName: 'ANn', playerId: '1', birthday: '2010-01-02' },
    { playerName: 'Eli', playerId: '2', birthday: '2011-01-02' },
    { playerName: 'Benn', playerId: '3', birthday: '2012-01-02' },
    { playerName: 'Klo', playerId: '4', birthday: '2013-01-02' },
    { playerName: 'Jhon', playerId: '5', birthday: '2014-01-02' },
    { playerName: 'Billy', playerId: '6', birthday: '2015-01-02' },
    { playerName: 'Dani', playerId: '7', birthday: '2015-01-02' },
    { playerName: 'Molly', playerId: '8', birthday: '2016-01-02' },
    { playerName: 'emily', playerId: '9', birthday: '2000-01-02' },
  ]);
  let secondOptions = players;

  if (year === '2010') {
    secondOptions = players.filter(
      (players) =>
        players.birthday >= '2010-01-01' && players.birthday <= '2010-12-31'
    );
  } else if (year === '2011') {
    secondOptions = players.filter(
      (players) =>
        players.birthday >= '2011-01-01' && players.birthday <= '2011-12-31'
    );
  } else if (year === '2012') {
    secondOptions = players.filter(
      (players) =>
        players.birthday >= '2012-01-01' && players.birthday <= '2012-12-31'
    );
  } else if (year === '2013') {
    secondOptions = players.filter(
      (players) =>
        players.birthday >= '2013-01-01' && players.birthday <= '2013-12-31'
    );
  } else if (year === '2014') {
    secondOptions = players.filter(
      (players) =>
        players.birthday >= '2014-01-01' && players.birthday <= '2014-12-31'
    );
  } else if (year === '2015') {
    secondOptions = players.filter(
      (players) =>
        players.birthday >= '2015-01-01' && players.birthday <= '2015-12-31'
    );
  } else if (year === '2016') {
    secondOptions = players.filter(
      (players) =>
        players.birthday >= '2016-01-01' && players.birthday <= '2016-12-31'
    );
  } else if (year === '2017') {
    secondOptions = players.filter(
      (players) =>
        players.birthday >= '2017-01-01' && players.birthday <= '2017-12-31'
    );
  } else if (year === '2018') {
    secondOptions = players.filter(
      (players) =>
        players.birthday >= '2018-01-01' && players.birthday <= '2018-12-31'
    );
  } else if (year === '2019') {
    secondOptions = players.filter(
      (players) =>
        players.birthday >= '2019-01-01' && players.birthday <= '2019-12-31'
    );
  } else if (year === '2000') {
    secondOptions = players.filter(
      (players) =>
        players.birthday >= '2000-01-01' && players.birthday <= '2000-12-31'
    );
  } else {
    secondOptions = [];
  }

  useEffect(() => {
    // Update the document title using the browser API
    console.log('playerat per ke optioni', secondOptions);
  });
  return (
    <div>
      <h1>Hello StackBlitz!</h1>
      <p>Start editing to see some magic happen :)</p>
      <select name="" id="" onChange={(e) => setyear(e.target.value)}>
        {/* <option value="2010">2010</option>
        <option value="2011">2011</option>
        <option value="2012">2012</option>
        <option value="2013">2013</option>
        <option value="2014">2014</option>
        <option value="2015">2015</option>
        <option value="2016">2016</option>
        <option value="2017">2017</option>
        <option value="2018">2018</option>
        <option value="2019">2019</option> */}
        {vitet.map((item) => (
          <option value={item}>{item}</option>
        ))}
      </select>
      <select>
        {secondOptions.map((item) => (
          <option key={item.playerId}>{item.playerName}</option>
        ))}
      </select>
      <p> {year}</p>
    </div>
  );
}

to have a look at a code editor you can see here.

https://stackblitz.com/edit/react-jruwh9

2 Answers2

2

Well, if you really want to treat dates as strings (check the notes at the end of the answer), what you can do there is the following

import React, { useState } from 'react';
import './style.css';

const years = [
  2030, 2029, 2028, 2027, 2026, 2025, 2024, 2023, 2022, 2021, 2020, 2019,
  2018, 2017, 2016, 2015, 2014, 2013, 2012, 2011, 2010, 2009, 2008, 2007,
  2006, 2005, 2004, 2003, 2002, 2001, 2000, 1999, 1998, 1997, 1996, 1995,
  1994, 1993, 1992, 1991, 1990, 1989, 1988, 1987, 1986, 1985, 1984, 1983,
  1982, 1981, 1980, 1979, 1978, 1977, 1976, 1975, 1974, 1973, 1972, 1971,
  1970, 1969, 1968, 1967, 1966, 1965, 1964, 1963, 1962, 1961, 1960, 1959,
  1958, 1957, 1956, 1955, 1954, 1953, 1952, 1951, 1950, 1949, 1948, 1947,
  1946, 1945, 1944, 1943, 1942, 1941, 1940, 1939, 1938, 1937, 1936, 1935,
  1934, 1933, 1932, 1931, 1930, 1929, 1928, 1927, 1926, 1925, 1924, 1923,
  1922, 1921, 1920, 1919, 1918, 1917, 1916, 1915, 1914, 1913, 1912, 1911,
];

const players = [
  { playerName: 'ANn', playerId: '1', birthday: '2010-01-02' },
  { playerName: 'Eli', playerId: '2', birthday: '2011-01-02' },
  { playerName: 'Benn', playerId: '3', birthday: '2012-01-02' },
  { playerName: 'Klo', playerId: '4', birthday: '2013-01-02' },
  { playerName: 'Jhon', playerId: '5', birthday: '2014-01-02' },
  { playerName: 'Billy', playerId: '6', birthday: '2015-01-02' },
  { playerName: 'Dani', playerId: '7', birthday: '2015-01-02' },
  { playerName: 'Molly', playerId: '8', birthday: '2016-01-02' },
  { playerName: 'emily', playerId: '9', birthday: '2000-01-02' },
];

export default function App() {
  const [year, setYear] = useState('');

  // With strings, as your code
  const secondOptions = players.filter(player => player.birthday.startsWith(`${year}-`));

  // Or, with Date (in this case it would be better to perform the conversion in the original object, instead of here, for better performance)
  // const secondOptions = players.filter(player => new Date(player.birthday).getFullYear() === year);

  return (
    <div>
      <h1>Hello StackBlitz!</h1>
      <p>Start editing to see some magic happen :)</p>
      <select onChange={(e) => setYear(e.target.value)}>
        {years.map((item) => (
          <option key={`year_option_${item}`} value={item}>{item}</option>
        ))}
      </select>
      <select>
        {secondOptions.map((item) => (
          <option key={`second_option_${item.playerId}`} value={item.playerId}>{item.playerName}</option>
        ))}
      </select>
      <p>{year}</p>
    </div>
  );
}

I moved some variables out of the component since, as they are now, they don't need to be in the component. Also, I added some missing keys and removed unused variables, for demonstration propose.

Important note about dates

Usually is better to treat dates as Date instead of strings.

If you decide to treat your dates ad Date instances, then you can use the functions you have available in JavaScript and do something similar of what I shown in the code I posted, in the filter section.

As mentioned by @GiorgiMoniava in the comments here, be careful of these kind of issues when converting a string to Date, if you opt for the Date solution

https://stackoverflow.com/a/22835394

Emanuele Scarabattoli
  • 4,103
  • 1
  • 12
  • 21
  • Filtering by "which string is bigger" is a wrong comparison as it does not work the same way as for ints. Just take the string date, turn into a date object and compare the years`new Date(player.birthday).getFullYear() === year` – Max Svidlo Mar 22 '22 at 12:48
  • @MaxSvid converting to date like that can be tricky due to timezone – Giorgi Moniava Mar 22 '22 at 12:55
  • @GiorgiMoniava and @Max, I changed to reply to include both `Date` and string options, so the user is able to decide with is the best for it, according to the notes too. I also added a `-` at the end of the string-based condition to avoid the unlikely, but not impossible, false positive with `20110` and `2011`. – Emanuele Scarabattoli Mar 22 '22 at 13:04
  • 1
    This is what I meant by tricky: https://stackoverflow.com/a/22835394 – Giorgi Moniava Mar 22 '22 at 13:09
  • @GiorgiMoniava I added a note about your point, thanks :) – Emanuele Scarabattoli Mar 22 '22 at 13:20
  • @EmanueleScarabattoli thats the best solution – Max Svidlo Mar 23 '22 at 13:42
  • SO SO SO Thank you for taking your time and helping me with this stuff i really do appreciate it. i have started learning react recently and can be kinda confusing at time – Jurgen Tafaj Mar 24 '22 at 23:03
  • hi if you can, might take a look on this one if you dont mind: https://stackoverflow.com/questions/71848862/showing-info-while-mapping-inside-of-array-for-date-inside-an-object-without-rep again thanks for helping with how much you can – – Jurgen Tafaj Apr 12 '22 at 20:42
0

I would start with optimizing your year selection. Use a start year, and fill an array up until now. Nobody is born the future... yet ;)

Next filter the years with only those that have players, next if you set the year, simply filter the players on the current year.

import React, { useState } from 'react';
import './style.css';

export default function App() {
  const START_YEAR = 1911;
  const END_YEAR = new Date().getFullYear() + 1;

  const [year, setyear] = useState('');
  const [players, setPlayers] = useState([
    { playerName: 'ANn', playerId: '1', birthday: '2010-01-02' },
    { playerName: 'Eli', playerId: '2', birthday: '2011-01-02' },
    { playerName: 'Benn', playerId: '3', birthday: '2012-01-02' },
    { playerName: 'Klo', playerId: '4', birthday: '2013-01-02' },
    { playerName: 'Jhon', playerId: '5', birthday: '2014-01-02' },
    { playerName: 'Billy', playerId: '6', birthday: '2015-01-02' },
    { playerName: 'Dani', playerId: '7', birthday: '2015-01-02' },
    { playerName: 'Molly', playerId: '8', birthday: '2016-01-02' },
    { playerName: 'emily', playerId: '9', birthday: '2000-01-02' },
  ]);

  const vitet = new Array(END_YEAR - START_YEAR)
    .fill(START_YEAR)
    .map((current, i) => current + i)
    .filter(
      (year) =>
        players.find(
          (player) => player.birthday.substr(0, 4) === year.toString()
        ) !== undefined
    );

  return (
    <div>
      <h1>Hello StackBlitz!</h1>
      <p>Start editing to see some magic happen :)</p>
      <select name="" id="" onChange={(e) => setyear(e.target.value)}>
        {vitet.map((item) => (
          <option value={item}>{item}</option>
        ))}
      </select>
      <select>
        {players
          .filter((player) => player.birthday.substr(0, 4) === year.toString())
          .map((item) => (
            <option key={item.playerId}>{item.playerName}</option>
          ))}
      </select>
      <p> {year}</p>
    </div>
  );
}
Ramses
  • 41
  • 3
  • this is way better version of what i did lol ty for taking your time to help me. i appreciate it so much. learning react recently and can be kinda confusing at times – Jurgen Tafaj Mar 24 '22 at 23:05
  • You're welcome! Keep in mind that i would also convert the string dates to actual Date objects as this would be an easier comparison. And you can format the dates to the users locale ;) 1 extra tip is, if you ever use `useEffect` stop and think again how you can remove that, to many side effects most of the time :D – Ramses Mar 28 '22 at 09:20
  • i mostly use useEffect when im making a database fetch but is there like anyway to remove that – Jurgen Tafaj Mar 28 '22 at 12:19
  • I mainly use [react-query](https://react-query.tanstack.com) for that, and make a custom hook for each fetch so you hide the boilerplate in the hook. e.g. `const { data: players } = useGetAllPlayers();` – Ramses Mar 30 '22 at 07:29
  • hi if you can, might take a look on this one if you dont mind: https://stackoverflow.com/questions/71848862/showing-info-while-mapping-inside-of-array-for-date-inside-an-object-without-rep again thanks for helping with how much you can – Jurgen Tafaj Apr 12 '22 at 20:40