skip to Main Content

I am trying to get an input field to appear when the user selects ‘other’ from the drop down menu. It was only appearing when I first got on the add recipes page, but I changes a few lines and then it stopped appearing all together. I am using FLask for the backend and it is pulling the cuisines from a database.

import React, { useState, useEffect } from 'react';
import { useNavigate } from 'react-router-dom';

function AddRecipe() {
  const navigate = useNavigate();
  const [formData, setFormData] = useState({
    name: '',
    description: '',
    ingredients: '',
    directions: '',
    prep_time: '',
    total_servings: '',
    image: '',
    cuisine_id: '',
    user_id: '', 
  });

  const [cuisines, setCuisines] = useState([]);
  const [otherCuisineName, setOtherCuisineName] = useState('');
  const [selectedCuisine, setSelectedCuisine] = useState('');
  const [successMessage, setSuccessMessage] = useState('');

  useEffect(() => {
    fetchCuisines();
  }, []);

  const fetchCuisines = async () => {
    try {
      const response = await fetch('/api/cuisines');
      const data = await response.json();
      setCuisines(data);
    } catch (error) {
      console.error('Error fetching cuisines:', error);
    }
  };

  const handleInputChange = (e) => {
    const { name, value } = e.target;
    setFormData({ ...formData, [name]: value });
  };

  const handleCuisineChange = (e) => {
    const value = e.target.value;
    console.log("Selected cuisine:", value);
    setSelectedCuisine(value);
    if (value === 'Other') {
      setOtherCuisineName('');
      document.getElementById('other-cuisine-input').style.display = 'block';
    } else {
      document.getElementById('other-cuisine-input').style.display = 'none';
    }
  };

  const handleOtherCuisineNameChange = (e) => {
    setOtherCuisineName(e.target.value);
  };

  const handleSubmit = async (e) => {
    e.preventDefault();
    let cuisineId;
    if (selectedCuisine === 'Other') {
      try {
        const response = await fetch('/api/cuisines', {
          method: 'POST',
          headers: {
            'Content-Type': 'application/json',
          },
          body: JSON.stringify({ name: otherCuisineName }),
        });
        const data = await response.json();
        cuisineId = data.id;
      } catch (error) {
        console.error('Error creating new cuisine:', error);
      }
    } else {
      cuisineId = selectedCuisine;
    }
    // Retrieves cuisine id
    formData.cuisine_id = cuisineId;
    try {
      const response = await fetch('/api/recipes', {
        method: 'POST',
        headers: {
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(formData),
      });
      const data = await response.json();
      console.log('Recipe created:', data);
      setSuccessMessage(`${formData.name} added!`);
      setFormData({
        name: '',
        description: '',
        ingredients: '',
        directions: '',
        prep_time: '',
        total_servings: '',
        image: '',
        cuisine_id: '',
        user_id: '', 
      });
      navigate('/recipes')
    } catch (error) {
      console.error('Error creating recipe:', error);
    }
  };

  return (
    <div className="addrecipe">
      <h2>Add Recipe</h2>
      <form onSubmit={handleSubmit}>
        <div className="addrecipe-card">
          {successMessage && <p>{successMessage}</p>}
          <label>Name:</label>
          <input
            type="text"
            name="name"
            placeholder="recipe name"
            value={formData.name}
            onChange={handleInputChange}
            required
          />
          <div>
            <label>Description:</label>
            <textarea
              name="description"
              placeholder="brief recipe description"
              value={formData.description}
              onChange={handleInputChange}
              required
            />
          </div>
          <div>
            <label>Ingredients:</label>
            <textarea
              name="ingredients"
              placeholder="recipe ingredients separated by commas"
              value={formData.ingredients}
              onChange={handleInputChange}
              required
            />
            <label>Directions:</label>
            <textarea
              name="directions"
              placeholder="recipe directions separated by periods."
              value={formData.directions}
              onChange={handleInputChange}
              required
            />
          </div>
          <div>
            <label>Prep Time (minutes):</label>
            <input
              type="number"
              name="prep_time"
              placeholder="approximate prep time"
              value={formData.prep_time}
              onChange={handleInputChange}
              required
            />
          </div>
          <div>
            <label>Total Servings:</label>
            <input
              type="number"
              name="total_servings"
              placeholder="total servings"
              value={formData.total_servings}
              onChange={handleInputChange}
              required
            />
          </div>
          <div>
            <label>Image Link:</label>
            <input
              type="text"
              name="image"
              value={formData.image}
              onChange={handleInputChange}
            />
          </div>
          <div>
            <label>Cuisine:</label>
            <select
              name="cuisine_id"
              value={selectedCuisine}
              onChange={handleCuisineChange}
              required
            >
              <option value="">Select cuisine...</option>
              {cuisines.map(cuisine => (
                <option key={cuisine.id} value={cuisine.id}>{cuisine.name}</option>
              ))}
              {/* Prevents duplicating of cuisines */}
              {!cuisines.some(cuisine => cuisine.name === 'Other') && (
                <option value="Other">Other</option>
              )}
            </select>

            <input
              id="other-cuisine-input"
              type="text"
              placeholder="Enter custom cuisine name"
              value={otherCuisineName}
              onChange={handleOtherCuisineNameChange}
              style={{ display: selectedCuisine === 'Other' ? 'block' : 'none' }}
            />
          </div>
          <button className="button" type="submit">Add Recipe</button>
        </div>
      </form>
    </div>
  );
}

export default AddRecipe;

2

Answers


  1. You should use npm dropdown library: Library
    Get data in a list and then just pass it to dropdown

    Login or Signup to reply.
  2. You are using display: none to show and hide your html and this is not a correact approach in React. The correct approach is using condional rendering – see: https://react.dev/learn/conditional-rendering

    So in you case you should remove direct HTML manipulation from

    const handleCuisineChange = (e) => {
        const value = e.target.value;
        console.log("Selected cuisine:", value);
        setSelectedCuisine(value);
      };
    

    Then in your JSX

                  {selectedCuisine === 'Other' && (
                      <input
                        id="other-cuisine-input"
                        type="text"
                        placeholder="Enter custom cuisine name"
                        value={otherCuisineName}
                        onChange={handleOtherCuisineNameChange}
                        style={{ display: selectedCuisine === 'Other' ? 'block' : 'none' }}
                      />
                    )}
    

    The snippet above uses logical AND operator. More on this approach here: https://react.dev/learn/conditional-rendering#logical-and-operator-

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search