DoneDeal0
DoneDeal0

Reputation: 6257

How to dynamically load a JSON file in React?

I need to populate a select input with a large list of countries. Because of internationalization, I have a separate json file for each language available. In order not to load all of them in my component, I would like to only import the one corresponding to the current locale.

Here is what I wrote:

function MyComponent() {
  const [countries, setCountries] = useState([]);
    const { locale } = useLocale();
  
  useEffect(() => {
    import(`../../data/countries/${locale}.json`)
      .then((res) => setCountries(res.countries))
      .catch(_ => null);
  }, []);
  
  return <Select options={countries}/>
  }

I also thought about writing my own hook in a separate file:

export const useFetchJSON = (file: string) => {
  const [data, setData] = useState({});
  const { locale } = useLocale();
  const res = require(`../data/${file}/${locale}.json`);
  setData(res);
  return data;
};

None of this techniques work. How to fix this? Thanks!

Upvotes: 4

Views: 5440

Answers (1)

lissettdm
lissettdm

Reputation: 13078

If you are not getting any error you can get the json data with res.default:

 useEffect(() => {
    import(`../../data/countries/${locale}.json`)
      .then((res) => setCountries(res.default.countries))
      .catch(_ => null);
  }, []);

If you are getting this error:

Module ./.json not declared as a System.registerDynamic dependency of

You should check your module bundle configuration.

Other solutions:

1.create an object to store the import functions:

const LocalesData = {
  en_AU: () => import("../../data/countries/en_AU.json"),
  es_ES: () => import("../../data/countries/es_ES.json"),
  //...
};

useEffect(() => {
  LocalesData[locale]()
    .then(res => console.log(res.default))
    .catch(_ => console.log("res", _));
}, []);

2. Move the static files to public folder and load the data using fetch:

  useEffect(() => {
    fetch(`${locale}.json`)
      .then(res => res.json())
      .then(res => console.log(res))
      .catch(_ => console.log(_));
  }, []);

Upvotes: 8

Related Questions