Reactでのwebアプリ作成中につまずいたりしたところ(主にTypeScript,React)
完全にメモ。
React,TypeScriptとかごちゃまぜで書くかも。あとでまとめてスクラップにするか記事にしてアウトプットする。
JavaScriptのオブジェクト操作時にキーに変数を使う
const keyName = 'thisIsKey';
const valueData = 'thisIsValue';
const obj = { [keyName]: valueData };
console.log(obj); // →→ {"thisIsKey": "thisIsValue"}
Reduxのdispatchに
入れ子になっているstate,
更新したいkey:value
を渡す。
↓
reducer で key:value のみを更新したい。
だが dispatch するときに参照したい object が "Cannot read properties of undefined" で エラー。
上手く dispatch に渡すにはどうしたものか。
最終的にやりたいのは、「複雑なネスト構造になっているstateの一部のみを更新」ということ。
「dispatch の引数に直接 state を代入する」のではなく、
「state を別の変数に代入してから dispatch の引数に渡す」
でエラーなく dispatch に渡せた
const sampleData:sampleType = {
...state
}
dispatch(actionCreator.updateState(sampleData));
複雑な入れ子になっている state の更新
例えばこんな感じ(実際はもっと入れ子がありました)
fukuzatsunaState = {
data1:{
field_data1:{
"value1":xx,
"value2":xx,
...
},
field_data2:{
"value1":xx,
"value2":xx,
...
}
}
data2:{
field_data1:{
"value1":xx,
"value2":xx,
...
},
field_data2:{
"value1":xx,
"value2":xx,
...
}
}
}
この state の "data1.field_data2.value1" のみを更新したい。
変更したい対象と操作したい state を dispatch するときに引数として渡す。
//型
export interface updateType{
target: string;
value: any;
}
//変更したい対象のデータ
const target: updateType = {
target:"value2",
value:"updateValue!"
}
//操作したいstate (型は省略)
const tmpStateData = {
...state
}
dispatch(actionCreator.updateState(target,tmpStateData);
actionCreator で受け取り。
interface updateState {
type:'UPDATE_STATE';
updateTarget:updateType;
stateData:tmpStateData;
}
export const actionCreator = {
updateState:(data:updateType, tmpStateData):AppThunkAction<any> => (dispatch) => {
dispatch({type:'UPDATE_STATE',updateTarget:data, stateData:tmpStateData});
}
}
ここからが本番。
reducer でどうするのか。
大きなデータの中から「ここだけ変更!」を自力で実装するのは大変だと思う。
だから「小さなデータに分解して、更新したら組み合わせる」方法で実装できた。
(...まとめ中)
関数呼び出し時に「() を付けたとき/付けないとき」の動作の違い
const arrowFunc1 = () => {
return 'function1'
}
それぞれ console でみてみると
console.log(arrowFunc1)
// () => {
// return 'function1'
// }
console.log(arrowFunc1())
// function1
関数を呼び出すときに () をつけないと
呼び出された関数そのもの
が返却され、() をつけると
呼び出した関数が実行された結果
が返却される。
console.dir()が意外と便利だった
JSONをコンソールで見たいときなんかに使うと○
こんなJSONをconsoleで見たい。
const jsonData = [
{
"Full Name": "Ines Kozey",
"Country": "India",
"Id": 0,
"Email": "Harrison_Lehner@willis.info"
},
{
"Full Name": "Karson Aufderhar",
"Country": "Nepal",
"Id": 1,
"Email": "Tiara_Kuhic@charlene.com"
},
{
"Full Name": "Holden Casper",
"Country": "Haiti",
"Id": 2,
"Email": "Cristopher@lesley.org"
},
{
"Full Name": "Paris Beatty",
"Country": "Nauru",
"Id": 3,
"Email": "Reece.Lynch@arnaldo.ca"
}
]
↓このように書く。
console.dir(jsonData)
結果は以下の通り。見やすいb
React Hook useEffect has a missing dependency: 'dispatch'. Either include it or remove the dependency array. の警告
lintはカスタムフックがライブラリからのものなのか、独自のものなのかを認識していないから警告がでていた。
↓のようなときは、第2引数に dispatch は必要ない。
useEffect(() => {
dispatch(actionCreators.xxxxx());
}, [dispatch]);
// ,[]); でok
【MUI】defautValue と value の違い
defaultValue → 初期値 変数が代入されるわけでは無い。
value → 実際の値。
let data = 2
defaultValue={date}
//コード上は変数(data)が渡されているが実際は '2' のみが渡されている。
// 結果 2
<TextField
defaultValue={'data'}
/>
としたとき、data が表示される。
data をRedux - actionCreatorから変更しようとしても data は変更されない。
<TextField
value={'data'}
/>
としたとき、同様に data が表示される。
data をRedux - actionCreatorから変更すると、Redux - actionCreatorの結果を返却し data に反映する。
しかし、onChangeを書いていないと TextField そのものを直接編集することはできない。
Redux - actionCreatorからも data を変更したいし、TextField そのものを直接編集もしたい時はどうするか。
→ value
と onChange
を使って TextField を生成する。
const [data, setData] = React.useState('data')
onChangeHandler = (event: React.ChangeEvent<HTMLInputElement>) =>{
setData(event.target.value)
}
dispatch(actionCreator.changeData(data))
<TextField
value={data}
onChange={(event) => (onChangeHandler(event))}
/>
MUI DataGrid のチェックボックスに初期値を設定する
consoleに取得したデータを表示してるよ
「型 'JSX.IntrinsicElements' に存在しません。」の対応
大文字で始まる型は JSX タグが React コンポーネントを参照していることを示しています。このような JSX タグはコンパイルを経てその大文字で始まる変数を直接参照するようになります。
とのこと。
小文字から始めるとタイトルのようなエラーが表示される。
//OK
function SampleJsx{
...
}
<SampleJsx />
//NG
function sampleJsx{
...
}
<sampleJsx />
import xx from @○○
tsconfig.json
にあらかじめパスを書いてあげると、カレントディレクトリを意識せずともimportができるようになる。
import {a, b} from '@○○';
import {c} from '@△△';
a();
b(arg1);
c(arg1, arg2);
{
"compilerOptions": {
"baseUrl": "base",
"paths": {
"@○○/*": ["○○/*"],
"@△△/*": ["△△/*"],
}
}
}