Search code examples
javascriptreactjsformsinputdynamicform

How can I get a <select> field to change dynamically based on the input from another <select> field in React?


I'm trying to get the "category" select field to change based on the selection from the "type" category. So if I select "income" from the first selection, then it will only show me the categories related to income (revenue, government credit). And if I select expenses, it will only show me categories for expenses (supplies, rent, internet, etc).

If you have advice, or a tutorial/video somewhere that I can follow that would really help me out. This is my first coding project I'm trying to complete, and I'm almost there :)

import React, { useState } from 'react'
import { useDispatch } from 'react-redux'

const AddToFinancials = ({setUpdate}) => {

    const dispatch = useDispatch()

    const [type, setType] = useState('')
    const [date, setDate] = useState('')
    const [amount, setAmount] = useState('')
    const [category, setCategory] = useState('')
    const [details, setDetails] = useState('')

    const handleAddExpense = (e) => {
        e.preventDefault()
        setUpdate()
        // dispatch()
    }

    return (
        <div>
            <div>
                <form className="ui form" onSubmit={handleAddExpense}>
                    <div className="ui fields">
                        <div className="ui field">
                            <select value={type} onChange={(e)=>setType(e.target.value)} className="ui fluid search dropdown" placeholder="Select type">
                                <option value="" disabled="disabled">Select transaction type</option>
                                <option>Income</option>
                                <option>Expense</option>
                                <option>RRSP Contribution</option>
                                <option>Donation</option>
                            </select>
                        </div>
                        <div className="ui field">
                            <input value={date} onChange={(e)=>setDate(e.target.value)} type="date" className="ui input" />
                        </div>
                        <div className="ui field">
                            <input value={amount} onChange={(e)=>setAmount(e.target.value)} className="ui input" type="text" placeholder="Amount"/>
                        </div>
                        
                        <div>
                            {()=>{
                            switch (type) {
                                case 'income':
                                    return (
                                        <div className="ui field">
                                            <select className="ui fluid search dropdown" placeholder="Select category">
                                                <option value="" disabled="disabled">Select category</option>
                                                <option>Revenue</option>
                                                <option>Government credit</option>
                                            </select>
                                        </div>
                                    )
                                case 'expense':
                                    return (
                                        <div className="ui field">
                                        <select  className="ui fluid search dropdown" placeholder="Select category">
                                                <option value="" disabled="disabled">Select category</option>
                                                <option>Advertising</option>
                                                <option>Supplies</option>
                                            </select>
                                            </div>
                                    )
                                case '':
                                    return (
                                        <div>
                                            <select>
                                                <option>non</option>
                                            </select>
                                        </div>
                                    )
                                default:
                                    return (
                                        <div className="ui field">
                                        <select  className="ui fluid search dropdown" placeholder="Select category">
                                                <option value="" disabled="disabled">Select category</option>
                                            </select>
                                            </div>
                                    )
                            }
                        }}
                                            
                        </div>           

                        <div className="ui field">
                            <input className="ui input" type="text" placeholder="Details"/>
                        </div>
                        <button type="submit" className="ui button">Add</button>
                    </div>                 
                </form>
            </div>
        </div>
    )
}

export default AddToFinancials

Solution

  • For sake of completeness, you could move this block:

    switch (type) {
      case 'income':
        return ( <
          div className = "ui field" >
          <
          select className = "ui fluid search dropdown"
          placeholder = "Select category" >
          <
          option value = ""
          disabled = "disabled" > Select category < /option> <
          option > Revenue < /option> <
          option > Government credit < /option> <
          /select> <
          /div>
        )
      case 'expense':
        return ( <
          div className = "ui field" >
          <
          select className = "ui fluid search dropdown"
          placeholder = "Select category" >
          <
          option value = ""
          disabled = "disabled" > Select category < /option> <
          option > Advertising < /option> <
          option > Supplies < /option> <
          /select> <
          /div>
        )
      case '':
        return ( <
          div >
          <
          select >
          <
          option > non < /option> <
          /select> <
          /div>
        )
      default:
        return ( <
          div className = "ui field" >
          <
          select className = "ui fluid search dropdown"
          placeholder = "Select category" >
          <
          option value = ""
          disabled = "disabled" > Select category < /option> <
          /select> <
          /div>
        )
    }

    into a function:

    const renderDetails = (type) => {
      switch (type) {
        ...
      }
    }

    and call the function in a div like this:

    <div>
      {renderDetails(type)}
    </div>

    Afterwards, I would move the whole renderDetails-function into a seperate module and import it, which would make it easier to create unit tests for it!