[react]usState()を使用して配列(feat.日記帳)を変更する
配列内のリスト内の項目を動的に変更する(条件付きレンダリング)
DiaryItem.jsに変更ボタンを生成します. 「修正」ボタンをクリックしてボタンを「修正解除」、「修正完了」ボタンに変更し、「修正完了」ボタンをクリックして再度修正し、「削除」ボタン(if関数とusStat関数を使用)に戻る
つまり、作成機能が必要なボタンは「修正」、「修正解除」、「修正完了」です. 修正ボタンをクリックし、日記本文にマウスカーソルを置き、書いた内容をtextareaに表示する機能 「修正」ボタンをクリックし、「修正解除」ボタンをクリックすると、作成中のコンテンツが表示される機能 修正完了ボタンをクリックし、修正中の内容を新しい内容に更新する必要があります. ここで,Reactの特性により,データは上から下へ一方向に流れ,イベントは下から上へ逆方向に流れた.
修正完了ボタンを考えると、新しいイベントが発生し、修正完了ボタン付きのDiaryItemが発生します.jsコンポーネントから親コンポーネントへApp.イベントはjsで渡す必要があるため、Appコンポーネントで変更すると関数が作成され、Appに変換されます.jsのサブコンポーネントDiaryList.jsアイテムにDiaryListを付けるjsのサブアセンブリDiaryItem.js道具をあげればいいです.(最終呼び出し関数の場所はDiaryItem.js)
💡使用する概念
🎯コーディング順序の整理
つまり、作成機能が必要なボタンは「修正」、「修正解除」、「修正完了」です.
修正完了ボタンを考えると、新しいイベントが発生し、修正完了ボタン付きのDiaryItemが発生します.jsコンポーネントから親コンポーネントへApp.イベントはjsで渡す必要があるため、Appコンポーネントで変更すると関数が作成され、Appに変換されます.jsのサブコンポーネントDiaryList.jsアイテムにDiaryListを付けるjsのサブアセンブリDiaryItem.js道具をあげればいいです.(最終呼び出し関数の場所はDiaryItem.js)
💡使用する概念
useState(), useRef(), props, onClick, !, onChange,3項演算子
もう一度復習しましょう.私たちはよく概念を破らなければなりません.🤩
📖例
1. App.js
import { useRef, useState } from "react";
import "./App.css";
import DiaryEditor from "./DiaryEditor";
import DiaryList from "./DiaryList";
const App = () => {
const [data, setData] = useState([]);
const dataId = useRef(0);
const onCreate = (author, content, emotion) => {
const created_date = new Date().getTime();
const newItem = {
author,
content,
emotion,
created_date,
id: dataId.current,
};
dataId.current += 1;
setData([newItem, ...data]);
};
const onDelete = (targetId) => {
const newDiaryList = data.filter((it) => it.id !== targetId);
setData(newDiaryList);
};
const onEdit = (targetId, newContent) => {
setData(
data.map((it) =>
it.id === targetId ? { ...it, content: newContent } : it
)
);
};
return (
<div className="App">
<DiaryEditor onCreate={onCreate} />
<DiaryList onEdit={onEdit} onDelete={onDelete} diaryList={data} />
</div>
);
};
export default App;
<コードの説明>
1) const onEdit = (targetId, newContent) => {
setData(
data.map((it) =>
it.id === targetId ? { ...it, content: newContent } : it
)
);
};
=関数の変更
何を修正するか分からないので、propとしてDiaryItemに渡されます.これはDiaryItemが実行する関数なので、修正パラメータの内容を受信する必要があります.
そこで,どの日記のターゲットIDを修正するか,どのように内容を修正するかのnewContentをパラメータとして入力する.
setDataを呼び出してデータの値を変更します.
dataにmapという関数を適用し、各要素が現在のパラメータとして渡されたtargetIdと一致しているかどうかを確認し、trueの場合、元のデータをすべてロードし、内容をnewContentに変更し、falseの場合itを返します.
mapという名前の組み込み関数は、すべての要素を巡回しながら新しい配列(変更された配列)を作成し、setDataに転送します.
onEdit関数は、変更ボタンのあるDiaryItemによって呼び出される必要があります.
2) <DiaryList onEdit={onEdit} onDelete={onDelete} diaryList={data} />
=propをサブアセンブリDiaryListに渡す(DiaryListはDiaryItemの親アセンブリ)
2. DiaryList.js
import DiaryItem from "./DiaryItem.js";
const DiaryList = ({ onEdit, onDelete, diaryList }) => {
return (
<div className="DiaryList">
<h2>일기리스트</h2>
<h4>{diaryList.length}개의 일기가 있습니다.</h4>
<div>
{diaryList.map((it) => (
<DiaryItem key={it.id} {...it} onEdit={onEdit} onDelete={onDelete} />
))}
</div>
</div>
);
};
export default DiaryList;
<コードの説明>
1) const DiaryList = ({ onEdit, onDelete, diaryList })
=親アプリケーション.jsコンポーネントからonEditをpropとして受信する
2) <DiaryItem key={it.id} {...it} onEdit={onEdit} onDelete={onDelete} />
=サブアイテムDiaryItem.別のpropをjsコンポーネントに渡す
3. DiaryItem.js⭐️
import { useRef, useState } from "react";
👉🏻const DiaryItem = ({
onEdit,
onDelete,
author,
content,
created_date,
emotion,
id,
}) => {
👉🏻const [isEdit, setIsEdit] = useState(false);
👉🏻const toggleIsEdit = () => setIsEdit(!isEdit);
👉🏻const [localContent, setLocalContent] = useState(content);
👉🏻const localContentInput = useRef();
const handleRemove = () => {
if (window.confirm(`${id + 1}번째 일기를 삭제하시겠습니까?`)) {
onDelete(id);
}
};
👉🏻const handleQuitEdit = () => {
setIsEdit(false);
setLocalContent(content);
};
👉🏻const handleEdit = () => {
if (localContent.length < 5) {
localContentInput.current.focus();
return;
}
if (window.confirm(`${id + 1}번쨰 일기를 수정하시겠습니까?`)) {
onEdit(id, localContent);
toggleIsEdit();
}
};
return (
<div className="DiaryItem">
<div className="info">
<span>
작 성 자 : {author} | 감 정 점 수 : {emotion}
</span>
<br />
<span className="date">
시 간 : {new Date(created_date).toLocaleString()}
</span>
<div className="content">
👉🏻{isEdit ? (
<>
<textarea
ref={localContentInput}
value={localContent}
onChange={(e) => setLocalContent(e.target.value)}
/>
</>
) : (
<>{content}</>
)}
</div>
👉🏻{isEdit ? (
<>
<button onClick={handleQuitEdit}>수 정 취 소</button>
<button onClick={handleEdit}>수 정 완 료 </button>
</>
) : (
<>
<button onClick={toggleIsEdit}>수 정 하 기</button>
<button onClick={handleRemove}>삭 제 하 기</button>
</>
)}
</div>
</div>
);
};
export default DiaryItem;
<コードの説明>
1) const DiaryItem = ({onEdit, onDelete, author, content, created_date, emotion, id})
=親DiaryListからpropからのonEdit関数を受信して呼び出す
1.ボタンの変更機能
1) const [isEdit, setIsEdit] = useState(false);
=userStateでfalse勘定科目isEditとしてデフォルト設定されているロールにはtrue、falseブール値があり、変更中か未変更のステータスがブール値であることを示します.
isEditがtrueの場合は、以下のJSXで修正中と見なして「修正解除」、「修正完了」ボタンにコードを記述し、「falseに変更」でない場合は「修正」または「削除」ボタンとします.
つまり、修正しているかどうかを示すコード!
2) {isEdit ? (
<>
<button onClick={handleQuitEdit}>수 정 취 소</button>
<button onClick={handleEdit}>수 정 완 료 </button>
</>
) : (
<>
<button onClick={toggleIsEdit}>수 정 하 기</button>
<button onClick={handleRemove}>삭 제 하 기</button>
</>
)}
=変更、削除ボタンのみが元の場所で3つの演算子を使用して変更を行った場合、変更を取り消し、変更ボタンを完了/変更でなければ、変更、削除ボタンとして追加されるコード.
3) const toggleIsEdit = () => setIsEdit(!isEdit);
=toggleEdit関数は、呼び出し時にIssetisEditを呼び出し、元のisEditが持つ値をnot演算で反転します.これは「修正」ボタンをクリックしたときに発生する関数です!!
3) {isEdit ? (
<>
<textarea
ref={localContentInput}
value={localContent}
onChange={(e) =>
setLocalContent(e.target.value)}
/>
</>
) : (
<>{content}</>
)}
=isEditと3つの演算子の使用
trueの場合はtextareaをlocalContentにインポートし、イベント(修正)が発生した場合はsetLocalContentに変更内容を渡すことでlocalContentを更新します.
falseの場合は、{content}がそのまま表示されます.
4) const [localContent, setLocalContent] = useState(content);
=localContentのuseState初期値をcontentに変更すると、[修正](Modify)ボタンをクリックしたときに作成された内容が表示されます.
💥しかし、これさえあれば、修正をクリックし、修正してからキャンセルをクリックすると、本来修正したい内容が再現されます.それを防ぐためにhandleQuitEditという関数を作成します.△話をするより、次のような間違った写真を参考にしたほうがいいです.
もう一度修正をクリックすると、以前に作成した内容が残したエラーを表示できます.
2.ボタンの変更をキャンセルする機能
1) const handleQuitEdit = () => {
setIsEdit(false);
setLocalContent(content);
};
=handleQuitEdit修正を終了するときに発生する関数
この関数を呼び出すとsetisEditはfalse(変更なし)になり、setLocalContentを使用してlocalContent値をcontentに変更します.(変更中のフォームはlocalContentによって管理されます!)
この関数をonClickイベントに挿入して、[修正をキャンセル](Cancel Modification)ボタンをクリックしたときに実行します.
3.修正ボタンの機能完了
1) const localContentInput = useRef();
=localContentInputは、textareaに注目するので、以下に指定した内容をマークします.
2) {isEdit ? (
<>
<textarea
ref={localContentInput}
value={localContent}
onChange={(e) =>
setLocalContent(e.target.value)}
/>
</>
) : (
<>{content}</>
)}
=textareaラベルにref機能を追加します.
2) const handleEdit = () => {
if (localContent.length < 5) {
localContentInput.current.focus();
return;
}
・・${id+1}本稼働日を変更しますか?if (window.confirm(
)) {
onEdit(id, localContent);
toggleIsEdit();
}
=handleEdit関数は呼び出さなければならない」
focus機能を提供するにはDOM要素を指定する必要がありますのでref機能が必要です.
(上端};
書き忘れないように)
🥲私の質問
localContent.current.focus();もう少しでそう書くところだった
さらによく考えてみるとlocalContentは修正内容であり、内容が含まれているところに焦点を当てるべきなので、内容が含まれているtextareaでrefを行うべきです.本当に腹立たしいですね.一つ一つのコードをよく考えなければなりません.忘れないでください.
🖥コード補完画面
日記作成完了ステータス
変更中のステータス
[修正完了]ボタンをクリックします
変更されたステータス
<不満な点は修正時間が変わらないこと…?>
🚀参考資料
反応講義-李正煥講義
Reference
この問題について([react]usState()を使用して配列(feat.日記帳)を変更する), 我々は、より多くの情報をここで見つけました
https://velog.io/@fltxld3/React-로-배열-수정하기-feat.일기장
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
1. App.js
import { useRef, useState } from "react";
import "./App.css";
import DiaryEditor from "./DiaryEditor";
import DiaryList from "./DiaryList";
const App = () => {
const [data, setData] = useState([]);
const dataId = useRef(0);
const onCreate = (author, content, emotion) => {
const created_date = new Date().getTime();
const newItem = {
author,
content,
emotion,
created_date,
id: dataId.current,
};
dataId.current += 1;
setData([newItem, ...data]);
};
const onDelete = (targetId) => {
const newDiaryList = data.filter((it) => it.id !== targetId);
setData(newDiaryList);
};
const onEdit = (targetId, newContent) => {
setData(
data.map((it) =>
it.id === targetId ? { ...it, content: newContent } : it
)
);
};
return (
<div className="App">
<DiaryEditor onCreate={onCreate} />
<DiaryList onEdit={onEdit} onDelete={onDelete} diaryList={data} />
</div>
);
};
export default App;
<コードの説明>
1)
const onEdit = (targetId, newContent) => {
setData(
data.map((it) =>
it.id === targetId ? { ...it, content: newContent } : it
)
);
};
=関数の変更何を修正するか分からないので、propとしてDiaryItemに渡されます.これはDiaryItemが実行する関数なので、修正パラメータの内容を受信する必要があります.
そこで,どの日記のターゲットIDを修正するか,どのように内容を修正するかのnewContentをパラメータとして入力する.
setDataを呼び出してデータの値を変更します.
dataにmapという関数を適用し、各要素が現在のパラメータとして渡されたtargetIdと一致しているかどうかを確認し、trueの場合、元のデータをすべてロードし、内容をnewContentに変更し、falseの場合itを返します.
mapという名前の組み込み関数は、すべての要素を巡回しながら新しい配列(変更された配列)を作成し、setDataに転送します.
onEdit関数は、変更ボタンのあるDiaryItemによって呼び出される必要があります.
2)
<DiaryList onEdit={onEdit} onDelete={onDelete} diaryList={data} />
=propをサブアセンブリDiaryListに渡す(DiaryListはDiaryItemの親アセンブリ)2. DiaryList.js
import DiaryItem from "./DiaryItem.js";
const DiaryList = ({ onEdit, onDelete, diaryList }) => {
return (
<div className="DiaryList">
<h2>일기리스트</h2>
<h4>{diaryList.length}개의 일기가 있습니다.</h4>
<div>
{diaryList.map((it) => (
<DiaryItem key={it.id} {...it} onEdit={onEdit} onDelete={onDelete} />
))}
</div>
</div>
);
};
export default DiaryList;
<コードの説明>
1)
const DiaryList = ({ onEdit, onDelete, diaryList })
=親アプリケーション.jsコンポーネントからonEditをpropとして受信する2)
<DiaryItem key={it.id} {...it} onEdit={onEdit} onDelete={onDelete} />
=サブアイテムDiaryItem.別のpropをjsコンポーネントに渡す3. DiaryItem.js⭐️
import { useRef, useState } from "react";
👉🏻const DiaryItem = ({
onEdit,
onDelete,
author,
content,
created_date,
emotion,
id,
}) => {
👉🏻const [isEdit, setIsEdit] = useState(false);
👉🏻const toggleIsEdit = () => setIsEdit(!isEdit);
👉🏻const [localContent, setLocalContent] = useState(content);
👉🏻const localContentInput = useRef();
const handleRemove = () => {
if (window.confirm(`${id + 1}번째 일기를 삭제하시겠습니까?`)) {
onDelete(id);
}
};
👉🏻const handleQuitEdit = () => {
setIsEdit(false);
setLocalContent(content);
};
👉🏻const handleEdit = () => {
if (localContent.length < 5) {
localContentInput.current.focus();
return;
}
if (window.confirm(`${id + 1}번쨰 일기를 수정하시겠습니까?`)) {
onEdit(id, localContent);
toggleIsEdit();
}
};
return (
<div className="DiaryItem">
<div className="info">
<span>
작 성 자 : {author} | 감 정 점 수 : {emotion}
</span>
<br />
<span className="date">
시 간 : {new Date(created_date).toLocaleString()}
</span>
<div className="content">
👉🏻{isEdit ? (
<>
<textarea
ref={localContentInput}
value={localContent}
onChange={(e) => setLocalContent(e.target.value)}
/>
</>
) : (
<>{content}</>
)}
</div>
👉🏻{isEdit ? (
<>
<button onClick={handleQuitEdit}>수 정 취 소</button>
<button onClick={handleEdit}>수 정 완 료 </button>
</>
) : (
<>
<button onClick={toggleIsEdit}>수 정 하 기</button>
<button onClick={handleRemove}>삭 제 하 기</button>
</>
)}
</div>
</div>
);
};
export default DiaryItem;
<コードの説明>
1)
const DiaryItem = ({onEdit, onDelete, author, content, created_date, emotion, id})
=親DiaryListからpropからのonEdit関数を受信して呼び出す1.ボタンの変更機能
1)
const [isEdit, setIsEdit] = useState(false);
=userStateでfalse勘定科目isEditとしてデフォルト設定されているロールにはtrue、falseブール値があり、変更中か未変更のステータスがブール値であることを示します.isEditがtrueの場合は、以下のJSXで修正中と見なして「修正解除」、「修正完了」ボタンにコードを記述し、「falseに変更」でない場合は「修正」または「削除」ボタンとします.
つまり、修正しているかどうかを示すコード!
2)
{isEdit ? (
<>
<button onClick={handleQuitEdit}>수 정 취 소</button>
<button onClick={handleEdit}>수 정 완 료 </button>
</>
) : (
<>
<button onClick={toggleIsEdit}>수 정 하 기</button>
<button onClick={handleRemove}>삭 제 하 기</button>
</>
)}
=変更、削除ボタンのみが元の場所で3つの演算子を使用して変更を行った場合、変更を取り消し、変更ボタンを完了/変更でなければ、変更、削除ボタンとして追加されるコード.3)
const toggleIsEdit = () => setIsEdit(!isEdit);
=toggleEdit関数は、呼び出し時にIssetisEditを呼び出し、元のisEditが持つ値をnot演算で反転します.これは「修正」ボタンをクリックしたときに発生する関数です!!3)
{isEdit ? (
<>
<textarea
ref={localContentInput}
value={localContent}
onChange={(e) =>
setLocalContent(e.target.value)}
/>
</>
) : (
<>{content}</>
)}
=isEditと3つの演算子の使用trueの場合はtextareaをlocalContentにインポートし、イベント(修正)が発生した場合はsetLocalContentに変更内容を渡すことでlocalContentを更新します.
falseの場合は、{content}がそのまま表示されます.
4)
const [localContent, setLocalContent] = useState(content);
=localContentのuseState初期値をcontentに変更すると、[修正](Modify)ボタンをクリックしたときに作成された内容が表示されます.💥しかし、これさえあれば、修正をクリックし、修正してからキャンセルをクリックすると、本来修正したい内容が再現されます.それを防ぐためにhandleQuitEditという関数を作成します.△話をするより、次のような間違った写真を参考にしたほうがいいです.
もう一度修正をクリックすると、以前に作成した内容が残したエラーを表示できます.
2.ボタンの変更をキャンセルする機能
1)
const handleQuitEdit = () => {
setIsEdit(false);
setLocalContent(content);
};
=handleQuitEdit修正を終了するときに発生する関数この関数を呼び出すとsetisEditはfalse(変更なし)になり、setLocalContentを使用してlocalContent値をcontentに変更します.(変更中のフォームはlocalContentによって管理されます!)
この関数をonClickイベントに挿入して、[修正をキャンセル](Cancel Modification)ボタンをクリックしたときに実行します.
3.修正ボタンの機能完了
1)
const localContentInput = useRef();
=localContentInputは、textareaに注目するので、以下に指定した内容をマークします.2)
{isEdit ? (
<>
<textarea
ref={localContentInput}
value={localContent}
onChange={(e) =>
setLocalContent(e.target.value)}
/>
</>
) : (
<>{content}</>
)}
=textareaラベルにref機能を追加します.2)
const handleEdit = () => {
if (localContent.length < 5) {
localContentInput.current.focus();
return;
}
・・${id+1}本稼働日を変更しますか?if (window.confirm(
)) {
onEdit(id, localContent);
toggleIsEdit();
}
=handleEdit関数は呼び出さなければならない」focus機能を提供するにはDOM要素を指定する必要がありますのでref機能が必要です.
(上端
};
書き忘れないように)🥲私の質問
localContent.current.focus();もう少しでそう書くところだった
さらによく考えてみるとlocalContentは修正内容であり、内容が含まれているところに焦点を当てるべきなので、内容が含まれているtextareaでrefを行うべきです.本当に腹立たしいですね.一つ一つのコードをよく考えなければなりません.忘れないでください.
🖥コード補完画面
日記作成完了ステータス
変更中のステータス
[修正完了]ボタンをクリックします
変更されたステータス
<不満な点は修正時間が変わらないこと…?>
🚀参考資料
反応講義-李正煥講義
Reference
この問題について([react]usState()を使用して配列(feat.日記帳)を変更する), 我々は、より多くの情報をここで見つけました
https://velog.io/@fltxld3/React-로-배열-수정하기-feat.일기장
テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol
Reference
この問題について([react]usState()を使用して配列(feat.日記帳)を変更する), 我々は、より多くの情報をここで見つけました https://velog.io/@fltxld3/React-로-배열-수정하기-feat.일기장テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol