razvanusc
razvanusc

Reputation: 179

Can't create a drop down button for my sorting method

Dropdown doesn't work. It shows up as dropped down all the time.

I have tried using something like the dropdown from react-boostrap; however that didn't work for me either. In that case the button never drops down. I tried downgrading my version of react-bootstrap but if I do that my code will break.

import React from "react";
import './Brewery.css'
import { Link } from 'react-router-dom';
import { ButtonToolbar, DropdownButton, MenuItem } from 'react- 
bootstrap';


class Brewery extends React.Component {
   constructor(props) {
    super(props);
    this.state = {
      showMenu: false,
      breweries: [],
      isOpen: false
    }
  }

  componentDidMount() {
    fetch("https://api.openbrewerydb.org/breweries")
      .then(response => response.json())
      .then((data) => {
        this.setState({
          breweries: data,
        })
      })
  }

  toggleOpen = () => this.setState({ isOpen: !this.state.isOpen });

  sortAlpha() {
      const breweries = [...this.state.breweries.slice(0,10)].sort((a, b) => {
        if (a.name < b.name) return -1;
        if (a.name > b.name) return 1;
        return 0;
      });
      this.setState({ breweries: breweries });
    }

  sortRevAlpha() {
    const breweries = [...this.state.breweries.slice(0,10)].sort((a, b) => {
      if (a.name < b.name) return 1;
      if (a.name > b.name) return -1;
      return 0;
    });
    this.setState({ breweries: breweries });
  }

 render() {

   const { breweries } = this.state;

   return(
    <div className="main-container">
      <div className="banner" styles="background-image: linear-gradient(-225deg, rgba(0,101,168,0.6) 0%, rgba(0,36,61,0.6) 50%), url('http://bitterminnesotabrewerytours.com/wp-content/uploads/2014/02/boston-beer-tours-glass.jpg');">
        <div className="banner-content">
          <h1>Brewery</h1>
          <p>Find the best brewery in town</p>
        </div>
      </div>
      <div className="container">
      <div className="dropdown">
        <button
        className="btn btn-secondary dropdown-toggle"
        type="button"
        id="dropdownMenuButton"
        data-toggle="dropdown"
        aria-haspopup="true"
        onClick={this.toggleOpen}
        >
        Dropdown
        </button>
        <div aria-labelledby="dropdownMenuButton">
          <a className="dropdown-item" href="#nogo">
            Item 1
          </a>
          <a className="dropdown-item" href="#nogo">
            Item 2
          </a>
          <a className="dropdown-item" href="#nogo">
            Item 3
          </a>
        </div>
        </div>
        <div>
          <button onClick={() => this.sortAlpha()}>Sort Alphabetically</button>
          <button onClick={() => this.sortRevAlpha()}>Sort Rev Alphabetically</button>
        </div>
        <div className="row">
          {breweries.slice(0, 10).map((brewery, i) =>
            <div className="col-xs-12 col-sm-4" key={i}>
              <Link to={`/brewery/${ brewery.id }`}>
                <div className="card">
                  <div className="card-description">
                    <h2>{brewery.brewery_type}</h2>
                    <p>{brewery.city}, {brewery.state}</p>
                  </div>
                  <div className="card-category"><img src="https://img.icons8.com/color/20/000000/beer.png"/>  {brewery.name}</div>
                </div>
              </Link>
            </div>
          )}
        </div>
      </div>
    </div>
    )
  }
}

export default Brewery;

Upvotes: 0

Views: 87

Answers (2)

Reed Dunkle
Reed Dunkle

Reputation: 3587

It looks like you aren't actually using this.state.isOpen. Your toggleOpen method toggles it, but I think you'll need to connect that this.state.isOpen value to your menu.

Ultimately you'll have to decide where you want it, but one solution that I've used before is to put it before your breweries map, so that the breweries list will only render if isOpen is truthy:

{ this.state.isOpen && breweries.slice(0, 10).map( // the rest of your code block here.

Also, since you're already destructuring this.state at the top of your render() method, I'd probably keep that consistent and pull out isOpen, and then remove the this.state from the && check.

Let me know how that goes or if you've got any questions.

Upvotes: 0

Dadsquatch
Dadsquatch

Reputation: 566

I haven't gone through with setting up the Router and testing everything locally, but when I did paste this into my IDE it shows that in the code you never actually use:

import { ButtonToolbar, DropdownButton, MenuItem } from 'react-bootstrap';

Edit:

Removed a few things and brought in react-bootstrap. Works just fine.

import React from "react";
import { ButtonToolbar, DropdownButton, MenuItem } from "react-bootstrap";

export class App extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      showMenu: false,
      breweries: []
    };
  }

  componentDidMount() {
    fetch("https://api.openbrewerydb.org/breweries")
      .then(response => response.json())
      .then(data => {
        this.setState({
          breweries: data
        });
      });
  }

  sortAlpha() {
    const breweries = [...this.state.breweries.slice(0, 10)].sort((a, b) => {
      if (a.name < b.name) return -1;
      if (a.name > b.name) return 1;
      return 0;
    });
    this.setState({ breweries: breweries });
  }

  sortRevAlpha() {
    const breweries = [...this.state.breweries.slice(0, 10)].sort((a, b) => {
      if (a.name < b.name) return 1;
      if (a.name > b.name) return -1;
      return 0;
    });
    this.setState({ breweries: breweries });
  }

  render() {
    const { breweries } = this.state;

    return (
      <div className="main-container">
        <div
          className="banner"
          styles="background-image: linear-gradient(-225deg, rgba(0,101,168,0.6) 0%, rgba(0,36,61,0.6) 50%), url('http://bitterminnesotabrewerytours.com/wp-content/uploads/2014/02/boston-beer-tours-glass.jpg');"
        >
          <div className="banner-content">
            <h1>Brewery</h1>
            <p>Find the best brewery in town</p>
          </div>
        </div>
        <div className="container">
          <ButtonToolbar>
            <DropdownButton
              bsSize="small"
              title="Small button"
              id="dropdown-size-small"
            >
              <MenuItem eventKey="1">Action</MenuItem>
              <MenuItem eventKey="2">Another action</MenuItem>
              <MenuItem eventKey="3">Something else here</MenuItem>
              <MenuItem divider />
              <MenuItem eventKey="4">Separated link</MenuItem>
            </DropdownButton>
          </ButtonToolbar>
        </div>
        <div>
          <button onClick={() => this.sortAlpha()}>Sort Alphabetically</button>
          <button onClick={() => this.sortRevAlpha()}>
            Sort Rev Alphabetically
          </button>
        </div>
        <div className="row">
          {breweries.slice(0, 10).map((brewery, i) => (
            <div className="col-xs-12 col-sm-4" key={i}>
              <div className="card">
                <div className="card-description">
                  <h2>{brewery.brewery_type}</h2>
                  <p>
                    {brewery.city}, {brewery.state}
                  </p>
                </div>
                <div className="card-category">
                  <img src="https://img.icons8.com/color/20/000000/beer.png" />{" "}
                  {brewery.name}
                </div>
              </div>
            </div>
          ))}
        </div>
      </div>
    );
  }
}

Make sure you add a link to bootstrap CSS at the bottom of your index.html in /public or react-bootstap won't work. It's just a wrapper.

// shortened to show code needed
  <link
      rel="stylesheet"
      href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css"
      integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u"
      crossorigin="anonymous"
    />
  </body>

Here is it working:

enter image description here

Upvotes: 1

Related Questions