8

I am making a basic app in reactjs. I've setup routes for 3 components. The problem is select fields don't appear when the component is rendered. I'm using bootstrap-select library for the select fields.

The select fields that have className as "selectpicker" do not render, they just aren't there. They showed up when I removed "selectpicker" from the className. When using "selectpicker", they show up when the browser page is reloaded.

Below is a snippet from my code: https://codesandbox.io/s/determined-panini-2mmv3 All three components are almost similar.

import React from 'react'
import A from "./A"
import B from "./B"
import C from "./C"
import {BrowserRouter as Router, Switch, Link, Route} from "react-router-dom"

class App extends React.Component{
  constructor(){
    super()
  }
    render(){
      return(
        <div>
          <Router>
            <ul>
              <li><Link to="/">TO A</Link></li>
              <li><Link to="/page1">TO B</Link></li>
              <li><Link to="/page2">TO C</Link></li>
            </ul> 
            <Switch>
              <Route exact path='/' component={A}/>
              <Route path='/page1' component={B}/>   {/* components B and C have select field with selectpicker class*/}
              <Route path="/page2" component={C}/>
            </Switch>
          </Router>
        </div>
      )
    }
}

export default App
{/*Component A*/}

import React from "react"

class A extends React.component{
  constructor(){
    super()
    this.state={
      componentA: ""
    }
    this.handleChange = this.handleChange.bind(this)
  }

  handleChange(event){
    const {name, value, type, checked} = event.target
    type === "checkbox" ? this.setState({ [name]: checked }) : this.setState({ [name]: value })
  }

  render(){
    return(
      <div className="form-group row">
        <label htmlFor="tempid" className="col-sm-2 col-form-label">Choose an option</label>
        <div className="col-sm-10">
            <select 
              className="form-control custom-select selectpicker"
              name = "componentA" 
              id = "tempid"
              value = {this.state.componentA}
              onChange = {this.handleChange} 
              required
            >
              <option value="" style={{display:"none"}} disabled selected>Choose one</option>
              <option value="p">P</option>
              <option value="q">Q</option>
              <option value="r">R</option>
              <option value="s">S</option> 
            </select>
        </div>
      </div>
    )
  }
}
export default A

Following is my index.html file, and i have included the bootstrap and bootstrap-select correctly. Its working fine when rendering the components individually. The problem arose when I started with routing.

<!DOCTYPE html>
<html lang="en"><head>
  <meta charset="utf-8">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <meta name="theme-color" content="#000000">
  <meta name="description" content="Web site created using create-react-app">

  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.10/css/bootstrap-select.min.css">


  <title>React App</title>

</head>
<body>
  <noscript>You need to enable JavaScript to run this app.</noscript>
  <div id="root"></div>

  <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
  <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-select/1.13.10/js/bootstrap-select.min.js" type="text/javascript"></script>

</body></html>

Here's the link to my problem's codesandbox https://codesandbox.io/s/determined-panini-2mmv3

Actual output: The select input fields with "selectpicker" class don't show up at all. Only the labels and other text inputs are visible. When the "selectpicker" className is removed, it works as expected. I get the following as output: My output

Expected: The select input field to be rendered. The expected should be as follows: enter image description here

CtrlAltElite
  • 487
  • 8
  • 32
  • 1
    @Semi-Friends Isn't the App component the parent component itself? Can you guide me to a source or any reference? – CtrlAltElite Sep 26 '19 at 12:23
  • 1
    Works fine for me: https://codesandbox.io/s/divine-cloud-vv3ob Did you properly include Bootstrap? –  Sep 26 '19 at 12:32
  • @ChrisG I've included my html file and Yes I have added bootstrap properly – CtrlAltElite Sep 26 '19 at 17:26
  • @ChrisG The exact same code is working in code-sandbox https://codesandbox.io/s/elegant-platform-5vpq2 But it is not working with visual studio code, even though all the correct dependencies are installed. Please have a look at the screenshots I have added to the question. – CtrlAltElite Sep 26 '19 at 18:39
  • 2
    That codesandbox is missing react-select's stylesheet, which is exactly what causes the original problem because it hides the ` –  Sep 26 '19 at 19:19
  • It is not react-select, but bootsrap-select that I am using. Plus I am trying not to lean towards jquery for a quick and dirty solution. but please do share your code on codesandbox @ChrisG It gives me an error that "selectpicker is not a function" when i tried pasting the same in my componentDidMount() – CtrlAltElite Sep 26 '19 at 19:55
  • What version of bootstrap and bootstrap-select are you using? – Jay Jordan Sep 27 '19 at 13:04
  • @JayJordan bootstrap 4.3.1 and bootstrap-select 1.13.10 – CtrlAltElite Sep 30 '19 at 01:51
  • Have you tried rolling back to 1.13.0? Also see the note https://developer.snapappointments.com/bootstrap-select/ – Jay Jordan Sep 30 '19 at 18:37
  • @JayJordan Tried that too. Doesn't work. – CtrlAltElite Oct 02 '19 at 19:33
  • @ChrisG Can you please tell me about the "selectpicker is not a function error". All I got from researching was it is caused due to jquery being not loaded properly or it being loaded twice. Or it is not loaded when the script is run. I am not sure how it is loaded twice. Any ideas? – CtrlAltElite Oct 11 '19 at 08:53
  • The error means that the selectpicker script isn't included or not called properly. `$().selectpicker` is therefore `undefined`, which is why `$().selectpicker()` causes the error. –  Oct 11 '19 at 09:09
  • @ChrisG Can you provide a functional example of your previous comment where you used ````$('select').selectpicker()```` in the ````componentDidMount()```` to make the problem work without removing any of the stylesheets – CtrlAltElite Oct 11 '19 at 09:52
  • Finally after so many days I was able to make it work using the answer from https://stackoverflow.com/questions/52464915/react-error-webpack-imported-module-4-jquery-default-modal-is-no/52464960 – CtrlAltElite Oct 11 '19 at 10:16

1 Answers1

3

I tried, as suggested by one of the comments on the question, to add $('select').selectpicker() in my componentDidMount(). But it did not work as expected. Instead I excountered an error __WEBPACK_IMPORTED_MODULE_8_jquery___default(…)(…).selectpicker is not a function. After struggling for days literally, I was able to fix the issue using the answer from React Error : __WEBPACK_IMPORTED_MODULE_4_jquery___default(...)(...).modal is not a function.

The import import $ from 'jquery' creates a local variable named $ inside your module, which then gets used by $('.selectpicker').selectpicker() (instead of the global $ you wanted).

The quickest fix would be to explicitly use the jQuery $ from the global context (which has been extended with your $.selectpicker() because you referenced that in your script tag.

window.$('.selectpicker').selectpicker()

CtrlAltElite
  • 487
  • 8
  • 32
  • 1
    While this has solved your problem, it should be noted that in the context of React, it's preferable not to mess with jQuery like that in the first place but to use proper React components instead. Bootstrap provides ``, and there are also some other libraries out there. –  Oct 11 '19 at 10:34
  • @ChrisG Yes I am aware. Though the select fields are rendering now, the validations that i have applied in the form do not work unless I reload the page. And I have tried a number of libraries. But I am looking for a select library that (1) lets me populate the options using an array of objects, (2) provides a "data-live-search" property, and (3) something like a "data-subtext" property that lets me include additional information inside the option, under the main text. And out of all the libraries I have tried, bootstrap-select is the best suited. – CtrlAltElite Oct 14 '19 at 05:27
  • Thats great. ```window.$('.selectpicker').selectpicker()``` works like a charm. – Ricardo Vigatti May 02 '21 at 17:32
  • Thanks for the answer, It solved my problem after two days! – Alireza Oct 26 '21 at 18:31