Search code examples
htmlreactjsforms

form with 2 int inputs where one always has to be lower and one always has to higher


I think its's pretty clear in my code what I am trying to do. basically I'm trying to use the max and min parameter from the input to make it so that they can never cross each other. This doesn't work of course, I am using react and am using usestate to set the values whenever the form is submitted and pass these variables into my database fetch. I feel like using 2 states one for the temporary value of the input and one to pass the submitted value to the fetch is not a good way of solving this.

const [ LowestPrice, setLowestPrice ] = useState(0)
const [ HighestPrice, setHighestPrice ] = useState(500)

useEffect(() =>{
const getProps = async () => {
const { data, count, error } = await backbase.from('products_2')
      .select('*', { count: 'exact' })
      .gte('price', LowestPrice)
      .lt('price', HighestPrice)
      .range(indexOfFirstItem, indexOfLastItem - 1)
}}, [LowestPrice, HighestPrice])

const handleSubmit = (e) => {
    e.preventDefault()

    setLowestPrice(document.getElementById("lowest_price")?.value)
    setHighestPrice(document.getElementById("highest_price")?.value)
  }

<form onSubmit={handleSubmit}>
        <label htmlFor="lowest_price">minimum price</label>
        <input
          type="number"
          id="lowest_price"
          defaultValue={LowestPrice}
          min={0}
          max={document.getElementById("highest_price")?.value}
        />
        <label htmlFor="highest_price">maximum price</label>
        <input
          type="number"
          id="highest_price"
          defaultValue={HighestPrice}
          min={document.getElementById("lowest_price")?.value}
          max={500}
        />
        <button type="submit">apply filters</button>
      </form>

I left out unessential parts of the code to make it easier to read. It's the min and max in the form that are the most relevant.


Solution

  • Firstly, don't use getElementById to listen to changes. React triggers a re-render on components when their value changes. In order to retain the value, we use useState. Secondly, you can use OnChange to compare between both values in state before deciding whether or not to discard the new value. Try something like this;

    const [lowestPrice, setLowestPrice] = useState(0);
    const [highestPrice, setHighestPrice] = useState(1);
    
    return (
    <form onSubmit={handleSubmit}>
        <label htmlFor="lowest_price">minimum price</label>
        <input
          onChange={e => e.target.value <= highestPrice && setLowestPrice(e.target.value)} value={lowestPrice}
          type="number"
          id="lowest_price"
          defaultValue={lowestPrice}
          value={lowestPrice}
          min={0}
          max={highestPrice}
        />
        <label htmlFor="highest_price">maximum price</label>
        <input
          onChange={e => e.target.value > lowestPrice && setHighestPrice(e.target.value)}
          type="number"
          id="highest_price"
          defaultValue={highestPrice}
          value={highestPrice}
          min={lowestPrice}
          max={500}
        />
        <button type="submit">apply filters</button>
      </form>
    )