React学習
React HooksのsetState等があることでclass componentを使う必要がなくなった。
functional component ベースでつくることができる。
useState(オブジェクト)
const [product, setProduct] = useState({
name: "",
price: "",
});
を上記のように定義したとき、このオブジェクトのひとつの要素のみを更新するには、このようにする。
onChange={(evt) => setProduct({ ...product, name: evt.target.value })}
...productがないと、name以外の要素(今回の場合price)をnull?(とりあえずなし)に初期化してしまう。
同じ関数内でsetCountを二度呼び出すには以下のようにする。セットした値が更新されないのは、setStateで値が更新されるのは関数が呼び出された後だから。
<button
onClick={() => {
setCount((prevCount) => prevCount + 1);
setCount((prevCount) => prevCount + 1);
}}
>
参考
useEffect
useEffect(() => {
console.log("useEffect invoked");
return () => {
// cleanup;
};
}, []);
第二引数が...
- []だと一回だけ実行
- なにもないと、画面更新のたびに実行
- []のなかにstateの名前を入れれば、それが更新された時にのみ実行
// cleanupの場所でそのコンポーネントが破棄されたときの処理を書く
displayステートによって表示を変える
{display && <Component /> }
api叩く
axiosをインストール
npm install axios
インポート
import axios from "axios";
初回にゲット
useEffect(() => {
axios.get("https://jsonplaceholder.typicode.com/posts").then((res) => {
setPosts(res.data);
});
// return () => {
// cleanup
// }
}, []);
普通に生のjsのfetchでもできる。
useEffect(() => {
fetch("https://jsonplaceholder.typicode.com/posts", {method: "GET"}).then(res => res.json()).then(data => {
setPosts(data);
})
}, []);
idを指定して、要素を取得する。idを用意して、fetchに埋め込む。
const [id, setId] = useState(1);
fetch(`https://jsonplaceholder.typicode.com/posts/${id}`, { method: "GET" })
.then((res) => res.json())
.then((data) => {
setPosts(data);
});
React HooksのuseContextを使うと親から孫に簡単に値を渡せる。
useReducer
ちょい微妙。dispatchってのを実行するとreducerの関数が実行される。countに状態が入っている。うん、理解。
import React, { useReducer } from "react";
const initialState = 0;
const reducer = (currentState, action) => {
switch (action) {
case "add":
return currentState + 1;
case "multiple":
return currentState * 2;
case "reset":
return initialState;
default:
return currentState;
}
};
const BasicReducer = () => {
const [count, dispatch] = useReducer(reducer, initialState);
return (
<div>
<div>Count {count} </div>
<button onClick={() => dispatch("add")}>+ 1</button>
<button onClick={() => dispatch("multiple")}>multiple * 3</button>
<button onClick={() => dispatch("reset")}>reset</button>
</div>
);
};
useReducer単体だと、そのコンポーネントの中でしか使えない...
そこで「useContext」。
useReducer + useContext。これでRedux的なグローバルな状態管理ができる。
useMemo
計算時間を最適化できる
関数だったisOddをuseMemo()の第一引数にしてあげるだけ。第二引数に変化がトリガーとなる値を指定する。今回の場合はcount。
const isOdd = useMemo(() => {
let i = 0;
//クソおそ処理
while (i < 500000000) i++;
return count % 2 !== 0;
}, [count]);
useCallback
React.memo
export default React.memo(aDisplay);
useCallbackの第二引数を[]にすることで初回だけのレンダリングに最適化できる。
const testFunction = useCallback(() => {
setCount((prev) => prev + 1);
}, []);
Reactにおいてのパフォーマンスの向上とは、不要なレンダリングを防ぐことを意味する。
Reactエラー
Objects are not valid as a React child (found: object with keys {name}). If you meant to render a collection of children, use an array instead.
下記の({ name, count }) を{}で囲み忘れると出る。
const aDisplay = ({ name, id }) => {
console.log(`display${name} `);
return <div>{id}</div>;
};
ここにまとまっているエラーのひとつ。
combineReducers
reducerをひとまとめにできる
const rootReducer = combineReducers({
reducer1,
reducer2,
});
ReactでREST API
Get
const getTask = () => {
axios
.get(`http://127.0.0.1:8000/api/tasks/${id}/`, {
headers: {
Authorization: "Token XXXXXXXXX",
},
})
.then((res) => {
setStateSomething(res.data);
});
};
Delete
const deleteTask = () => {
axios
.delete(`http://127.0.0.1:8000/api/tasks/${id}/`, {
headers: {
Authorization: "Token XXXXXXXXX",
},
})
.then((res) => {
console.log(res)
});
};
new(post)
const newTask = (task) => {
//ここで新たに追加するデータを用意する
const data = {
title: task.title,
};
//第二引数でdataを渡す
axios
.post(`http://127.0.0.1:8000/api/tasks/`, data, {
headers: {
"Content-Type": "application/json",
Authorization: "Token XXXXXXXXX",
},
})
.then((res) => {
setTasks([...tasks, res.data]);
setEditedTask({ id: "", title: "" });
});
};
edit(put)
const editTask = (task) => {
axios
.put(`http://127.0.0.1:8000/api/tasks/${task.id}/`, task, {
headers: {
"Content-Type": "application/json",
Authorization: "Token XXXXXXXXX",
},
})
.then((res) => {
setTasks(
tasks.map((task) => (task.id === editedTask.id ? res.data : task))
);
setEditedTask({ id: "", title: "" });
});
};
onClickのなかでの関数実行気をつけないと。() => deleteTask(task.id)って書く。
<button onClick={() => deleteTask(task.id)}>
<i className="fas fa-trash-alt"></i>
</button>
inputで入力できないないなと思ったら、setStateSomething()がうまくいってない!