KAEDE Hack blog

JavaScript 中心に ライブラリなどの使い方を解説する技術ブログ。

React で ./src/locales/ の中身を全て読み取ろうとしたが無理だった - react は複数の json を読み込めない!

why

kei-s-lifehack.hatenablog.com

前回の記事で 5言語の切り替えを実装したが、毎回

import xxJson from './locales/xx.json'

xx: {                  
  translation: xxJson, 
},                     

<button onClick={     
  () => setLang('xx') 
}>                    
  XXXXXX

これを書かないと言語を追加できないクソ設計なので直す

やったこと

react-i18next で json ファイルを map しようとした

fs で map しようとするけどどの代替ライブラリを使ってもできなかった

teratail.com

Reactでfsは使えません。 React動かすのは大抵ブラウザ上でしょ?

説明ページの中身をよく読んで、これはNode.js上で動かす事を想定しているのか、 JavaScript上で動かす事を想定しているのか推測してください。

teratail で完璧な回答があった.....

解決策

一つの json file にデータを置いて map する

medium.com

map する先の json は 1 file!

それの実行は次回の記事

記事のURL をここに入れろ!!!

失敗した取り組み

fs をまず使ってみるがダメ

path と fs のライブラリを使ってフォルダから読み込んで cll に出力してみる

両方 Node の根幹だから import は必要ない。

const localesDir = path.join(process.cwd(), 'locales')
console.log(localesDir);

これで

/locales

path が 作れてる

fs.readdirSync を...

あれ?

fsWEBPACK_IMPORTED_MODULE_3_default.a.readdirSync is not a function

ググってみると

stackoverflow.com

se brfs , https://github.com/browserify/brfs

fs.readFileSync() and fs.readFile() static asset browserify transform

ブラウザだから使えないようなことが書いてある

fs 以外で使えるものをいろいろググってみるが全滅

brfs は毎回ビルドになる

browserify というシステムの brfs

browserify.org

コンパイラで毎回ビルドするのはやってることと違うので拒否

browserify-fs を使うが同じエラーが出る

github.com

この fs 互換で行けるか?

import fs from 'browserify-fs'

const fileNames = fs.readdirSync(localesDir);

browserify_fsWEBPACK_IMPORTED_MODULE_3_default.a.readdirSync is not a function

readdirSync がない.... 同じエラーだ...

brfs の方だと bundle しないといちいちビルドしないと実行できなくなるってことになる、それは開発効率下がるからしたくない

list-react-files を試すが fs を結局使っている

stackoverflow.com

list-react-files というライブラリがあるらしい

npm i list-react-files

import listReactFiles from 'list-react-files'

listReactFiles(__dirname).then(files => console.log(files))

Promise か....展開して... あれ?

glob.js:547 Uncaught (in promise) TypeError: fs.readdir is not a function
    at Glob.push../node_modules/glob/glob.js.Glob._readdir (glob.js:547)
    at Glob.push../node_modules/glob/glob.js.Glob._processGlobStar (glob.js:625)
    at Glob.push../node_modules/glob/glob.js.Glob._process (glob.js:362)
    at new Glob (glob.js:170)
    at glob (glob.js:75)
    at index.js:29
    at new Promise (<anonymous>)
    at listReactFiles (index.js:28)

listReactFiles は glob を使っていて、glob も fs.readFiles を使っているからダメらしい。

indeed, it throws Unhandled Rejection (TypeError): fs.readdir is not a function – Mugen Jun 18 '19 at 13:34

コメントに書いてある通りやんけ

list-files を使う

リプライがないけど、最後の回答を試してみる

import find from 'list-files'

find(function(result) {
    console.log(result); 
  } ,{
    dir: localesDir,
    name: 'json'
});

index.js:19 Uncaught TypeError: exec is not a function

stackoverflow.com

exec を 使うらしい

const exec  = require('child_process').exec;

実際に使うと

dentifier 'exec' has already been declared (14:7)

import zhJson from './locales/zh.json'

を指摘されてしまう。exec がすでにされているってことらしい

www.freecodecamp.org

exec の基礎が何もわかっていない....

fs でのエラーハンドリング

いろいろ試したけどファイルからの json ファイル名の取得すらできない....

そもそもエラーハンドリングをしないと使えない?

https://www.codegrepper.com/code-examples/javascript/list+all+files+in+dir+react

fs.readdir(localesDir, function (err, files) {
    //handling error
    if (err) {
        return console.log('Unable to scan directory: ' + err);
    } 
    //listing all files using forEach
    files.forEach(function (file) {
        // Do whatever you want to do with the file
        console.log(file); 
    });
});

fsWEBPACK_IMPORTED_MODULE_3_default.a.readdir is not a function

まず readdir が fs にないって言われてしまってどうしようもない...