javascriptreactjsdropdown

Conditional dropdowns in React JS


I'm building a Dnd Character Sheet builder. I need 6 dropdowns for each of the 6 main stats. I want them all to have access to an array of the values [8,10,12,13,14,15], but if one dropdown selects a number, I need that number to be unavailable in the dropdowns. So if the user chooses 15 for the strength score, the other dropdowns would no longer have the option to choose 15.

This is where I build the dropdowns.

    <div>
      {standardArray.map((stat, index) => {
        return (
          <div key={index}>
            <Text marginLeft={5}> {stat.name[index]}</Text>
            <Select
              placeholder={stat.name[index]}
              width="90%"
              marginLeft={3}
              marginBottom={3}
              onChange={handleChange}
              name={"playerStat" + [index]}
            >
              Name: {stat.name}
              {stat.value.map((value, index) => {
                return (
                  <option key={index} value={value}>
                    {value}
                  </option>
                );
              })}
            </Select>
          </div>
        );
      })}
    </div>

and these are the arrays and the value assignments

function App() {
  const [count, setCount] = useState(0);
  const statArray = [8, 10, 12, 13, 14, 15];
  const statTitles = ["STR", "CON", "DEX", "INT", "WIS", "CHA"];
  const standardArray = [
    { id: 1, name: statTitles, value: statArray },
    { id: 2, name: statTitles, value: statArray },
    { id: 3, name: statTitles, value: statArray },
    { id: 4, name: statTitles, value: statArray },
    { id: 5, name: statTitles, value: statArray },
    { id: 6, name: statTitles, value: statArray },
  ];

  const [state, setState] = useState({
    playerName: "Test",
    playerSpecies: "",
    playerClass: "",
    playerSubclass: "",
    playerStat0: 15,
    playerStat1: 14,
    playerStat2: 13,
    playerStat3: 10,
    playerStat4: 8,
    playerStat5: 12,
    playerLevel: 1,
    strModifier: 0,
    conModifier: 0,
    dexModifier: 0,
    intModifier: 0,
    wisModifier: 0,
    chaModifier: 0,
    playerHp: 24,
    proficiencyBonus: 2,
    speciesBonus: 0,
  });

Solution

  • you can filter the ones in use such as:

    import React from 'react';
    
    const allowedValues = [8, 10, 12, 13, 14, 15];
    const stats = [
      'strength',
      'dexterity',
      'constitution',
      'intelligence',
      'wisdom',
      'charisma',
    ];
    const notInUse = array => values =>
      array.filter(v => !values.map(String).includes(String(v)));
    
    export function App(props) {
      const [inUse, setInUse] = React.useState(Array(stats.length).fill(''));
    
      const handleChange = (index, value) => {
        const newInUse = [...inUse];
        newInUse[index] = value ? Number(value) : '';
        setInUse(newInUse);
      };
    
      return (
        <div className='App'>
          <h1>Hello Nerd.</h1>
          {stats.map((stat, index) => (
            <div key={stat}>
              <label tyle={{ padding: '16px' }}>
                {stat}: {inUse[index]} {'  '}
              </label>
              <select
                value={inUse[index]}
                onChange={e => handleChange(index, e.target.value)}
              >
                <option value=''>Select a value</option>
                {notInUse(allowedValues)(inUse).map(value => (
                  <option key={value} value={value}>
                    {value}
                  </option>
                ))}
              </select>
            </div>
          ))}
        </div>
      );
    }
    
    // Log to console
    console.log('Hello console');
    

    And it should adjust:

    i.E

    example