2

I want to duplicate Material UI's language changer https://material-ui.com/.

So as you can see, I wrapped an icon + Mui Select into a Mui Button. By the way, if you have an idea for a better implementation you're welcome!

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import { Select, MenuItem, Button } from '@material-ui/core';
import { useTranslation } from 'react-i18next';
import TranslateIcon from '@material-ui/icons/Translate';

const useStyles = makeStyles(() => ({
  root: {
    '&:before': {
      borderColor: 'white',
    },
    '&:after': {
      borderColor: 'white',
    },
    color: 'white',
  },
}));

const LanguageChanger = () => {
  const classes = useStyles();
  const { i18n, t } = useTranslation();
  const listLanguage = React.createRef();

  const langSwitch = [
    { code: 'en-US', title: t('Language.English') },
    { code: 'fr', title: t('Language.French') },
  ];

  const handleChange = event => {
    i18n.changeLanguage(event.target.value);
  };

  const renderSelect = language => {
    return (
      <Button
        color='inherit'
        onClick={() => {
          console.log(listLanguage);
          listLanguage.current.click();
        }}
      >
        <TranslateIcon />
        <Select
          className={classes.root}
          id='select-language'
          ref={listLanguage}
          value={language}
          onChange={handleChange}
        >
          {langSwitch.map((lang, index) => {
            return (
              <MenuItem key={index} value={lang.code}>
                {lang.title}
              </MenuItem>
            );
          })}
        </Select>
      </Button>
    );
  };

  return renderSelect(i18n.language);
};

export default LanguageChanger;

My problem here is to open MuiSelect with a click on his parent's Mui Button. No errors, the Mui Select is just taking the focus.

1 Answer 1

3

I had a similar problem and solved it like this SandBox using a state to handle the Select open flag, not the best solution in my opinion by it works.

import React from "react";
import { makeStyles } from "@material-ui/core/styles";
import { Select, MenuItem, Button } from "@material-ui/core";
import { useTranslation } from "react-i18next";
import TranslateIcon from "@material-ui/icons/Translate";

const useStyles = makeStyles(() => ({
  root: {
    "&:before": {
      borderColor: "white"
    },
    "&:after": {
      borderColor: "white"
    },
    color: "white"
  }
}));

const App = () => {
  const classes = useStyles();
  const { i18n, t } = useTranslation();
  const [open, setOpen] = React.useState(false);

  const langSwitch = [
    { code: "en-US", title: t("Language.English") },
    { code: "fr", title: t("Language.French") }
  ];

  const handleChange = (event) => {
    i18n.changeLanguage(event.target.value);
  };

  const renderSelect = (language) => {
    return (
      <Button
        color="inherit"
        onClick={() => {
          setOpen(!open);
        }}
      >
        <TranslateIcon />
        <Select
          className={classes.root}
          id="select-language"
          onClick={() => setOpen(!open)}
          value={language}
          onChange={handleChange}
          open={open}
        >
          {langSwitch.map((lang, index) => {
            return (
              <MenuItem key={index} value={lang.code}>
                {lang.title}
              </MenuItem>
            );
          })}
        </Select>
      </Button>
    );
  };

  return renderSelect(i18n.language);
};

export default App;

Sign up to request clarification or add additional context in comments.

4 Comments

This works! Thank you, I didn't think about that open props.
Could you add some code snippets from your solution please? Sometimes URLs can get broken, at least some part of the answer will stay here for others to find. Thanks
Sure, unfortunally I cannot update the answer and the code is too many chars to be pasted, do you have a suggestion how I can solve this?
You should be able to update your answer with code from App.js file with no problem. I will try that for you

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.