Search code examples
cssreactjshtml-selectreact-bootstrap

Flags inside a React Bootstrap select option renders as [object, object]


I want to display Flags icons inside a React Bootstrap selection Option. I have tried both CSS based and React based libraries to do so and in each case I get only [object object]

enter image description here

I have tried with the https://github.com/lipis/flag-icon-css CSS library

<Form.Control as="select">
         <option><span className="flag-icon flag-icon-gr"></span></option>
</Form.Control>

Which gives me a warning and the same [Object object]

Warning: Only strings and numbers are supported as <option> children.

I have also attempted with the React wrapper for the same library https://www.npmjs.com/package/react-flag-icon-css

<Form.Control as="select">
        <option><FlagIcon className="countryIcon" code="us" size="lg"/></option>
</Form.Control>

Which does not generate a warning but no results either

Does anyone know how I can get something else than string or number in the Option, or another way to include an icon ?


Solution

  • Option HTML tag accepts text only, it can't accept any other HTML, it will strip it. You can check this React issue [bug][16.5.0] option returns [object Object] instead of string and read the comment by Dan Abramov:

    I don't think it was strictly a regression. This is kind of a thorny area. It was never intentionally supported. It accidentally worked on initial mount but then crashed on updates (#13261). Fixing the crash was more important, so we fixed it to be treated as text content (which it should be). Unfortunately this means putting custom components in the middle is not supported. That's consistent with how textarea and similar elements work.

    I think it's better to show invalid output and warn about something that breaks on updates, than to let people use it only to discover it crashes in production. But I can see arguments for why this should be supported when the custom component returns a string. Unfortunately I don't know how to fix it in a way that would both solve the update crashes and support text-only content. I think for now it's reasonable to say putting custom components into doesn't really work (and never quite worked correctly), and ask you to manually provide a string to it.

    Alternatively, you can use Bootstrap Dropdowns to create a dropdown button with a list of countries using the code below:

    App.js:

    ...
    import Dropdown from 'react-bootstrap/Dropdown';
    import FlagIcon from './FlagIcon.js'
    
    function App() {
      const [countries] = useState([
        { code: 'gr', title: 'Greece'},
        { code: 'gb', title: 'United Kingdom'},
        { code: 'us', title: 'United States'}
      ]);
      const [toggleContents, setToggleContents] = useState("Select a country");
      const [selectedCountry, setSelectedCountry] = useState();
    
      return (
        <div className="App">
          <Form>
            <Dropdown
              onSelect={eventKey => {
                const { code, title } = countries.find(({ code }) => eventKey === code);
    
                setSelectedCountry(eventKey);
                setToggleContents(<><FlagIcon code={code}/> {title}</>);
              }}
            >
              <Dropdown.Toggle variant="secondary" id="dropdown-flags" className="text-left" style={{ width: 300 }}>
                {toggleContents}
              </Dropdown.Toggle>
    
              <Dropdown.Menu>
                {countries.map(({ code, title }) => (
                  <Dropdown.Item key={code} eventKey={code}><FlagIcon code={code}/> {title}</Dropdown.Item>
                ))}
              </Dropdown.Menu>
            </Dropdown>
          </Form>
        </div>
      );
    }
    

    FlagIcon.js:

    import React from 'react';
    import FlagIconFactory from 'react-flag-icon-css';
    
    // const FlagIcon = FlagIconFactory(React);
    // If you are not using css modules, write the following:
    const FlagIcon = FlagIconFactory(React, { useCssModules: false })
    
    export default FlagIcon;
    

    You'll get a dropdown button like this:

    Bootstrap Dropdown Button Menu

    You can also check this working Stackblitz: https://stackblitz.com/edit/react-bootstrap-flags-dropdown-menu