[英]Should I use the Redux store to pass data from child to parent?
I am building a to-do/notes app in order to learn the basics of Redux, using React hooks and Typescript.我正在构建一个待办事项/笔记应用程序,以便使用 React 挂钩和 Typescript 学习 Redux 的基础知识。
A note is composed of an ID and a value.注释由 ID 和值组成。 The user can add, delete or edit a note.用户可以添加、删除或编辑注释。
The add / delete mechanics work fine.添加/删除机制工作正常。 But the edit one is trickier for me, as I'm questionning how it should be implemented.但是编辑对我来说比较棘手,因为我在质疑应该如何实施它。
I think my reducer's code is fine.我认为我的减速器代码很好。 The problem lies between my component (Note.tsx) and its parent one (App.tsx).问题出在我的组件 (Note.tsx) 和它的父组件 (App.tsx) 之间。
When i'm logging the value, I can see that the new updated/edited value of the note is not sent to the reducer.当我记录值时,我可以看到注释的新更新/编辑值没有发送到减速器。 As a result, my note is not edited with the new value.结果,我的笔记未使用新值进行编辑。
I've tried "cloning" the redux store and making my changes here, but it seems tedious and unnatural to me.我试过“克隆”redux 商店并在此处进行更改,但对我来说这似乎乏味且不自然。 Should I just call the edit method from my Note.tsx component?我应该只从我的 Note.tsx 组件调用编辑方法吗?
Is there a clean / conventional way to do this?有没有一种干净/传统的方法来做到这一点?
Here is my code:这是我的代码:
App.tsx应用程序.tsx
function App() {
const notes = useSelector<NotesStates, NotesStates['notes']>(((state) => state.notes));
const dispatch = useDispatch();
const onAddNote = (note: string) => {
dispatch(addNote(note));
};
const onDeleteNote = (note: NoteType) => {
dispatch(deleteNote(note));
};
const onEditNote = (note: NoteType) => {
dispatch(updateNote(note));
};
return (
<div className="home">
<NewNoteInput addNote={onAddNote} />
<hr />
<ul className="notes">
{notes.map((note) => (
<Note
updateNote={() => onEditNote(note)}
deleteNote={() => onDeleteNote(note)}
note={note}
/>
))}
</ul>
</div>
);
}
Note.tsx笔记.tsx
interface NoteProps {
deleteNote(): void
updateNote(noteValue: string | number): void
note: NoteType
}
const Note: React.FC<NoteProps> = ({ deleteNote, updateNote, note: { id, value } }) => {
const [isEditing, setIsEditing] = useState(false);
const [newNoteValue, setNewNoteValue] = useState(value);
const onDeleteNote = () => {
deleteNote();
};
const onUpdateNote = () => {
updateNote(newNoteValue);
setIsEditing(false);
};
const handleOnDoubleClick = () => {
setIsEditing(true);
};
const renderBody = () => {
if (!isEditing) {
return (
<>
{!value && <span className="empty-text">Note is empty</span>}
<span>{value}</span>
</>
);
}
return (
<input
value={newNoteValue}
onChange={(e) => setNewNoteValue(e.target.value)}
onBlur={onUpdateNote}
/>
);
};
return (
<li className="note" key={id}>
<span className="note__title">
Note n°
{id}
</span>
<div className="note__body" onDoubleClick={handleOnDoubleClick}>
{renderBody()}
</div>
<button type="button" onClick={onDeleteNote}>Delete</button>
</li>
);
};
export default Note;
and the notesReducer.tsx和 notesReducer.tsx
export interface NotesStates {
notes: Note[]
}
export interface Note {
id: number
value: string
}
const initialState = {
notes: [],
};
let noteID = 0;
export const notesReducer = (state: NotesStates = initialState, action: NoteAction): NotesStates => {
switch (action.type) {
case 'ADD_NOTE': {
noteID += 1;
return {
...state,
notes: [...state.notes, {
id: noteID,
value: action.payload,
}],
};
}
case 'UPDATE_NOTE': {
return {
...state,
notes: state.notes.map((note) => {
if (note.id === action.payload.id) {
return {
...note,
value: action.payload.value,
};
}
return note;
}),
};
}
case 'DELETE_NOTE': {
return {
...state,
notes: [...state.notes
.filter((note) => note.id !== action.payload.id)],
};
}
default:
return state;
}
};
Thanks to @secan in the comments I made this work, plus some changes.感谢 @secan 在我的评论中做出了这项工作,并进行了一些更改。
In App.tsx:在 App.tsx 中:
<Note
updateNote={onEditNote}
deleteNote={() => onDeleteNote(note)}
note={note}
/>
In Note.tsx:在 Note.tsx 中:
interface NoteProps {
deleteNote(): void
updateNote(newNote: NoteType): void // updated the signature
note: NoteType
}
// Now passing entire object instead of just the value
const onUpdateNote = (newNote: NoteType) => {
updateNote(newNote);
setIsEditing(false);
};
const renderBody = () => {
if (!isEditing) {
return (
<>
{!value && <span className="empty-text">Note is empty</span>}
<span>{value}</span>
</>
);
}
return (
<input
value={newNoteValue}
onChange={(e) => setNewNoteValue(e.target.value)}
// modifying current note with updated value
onBlur={() => onUpdateNote({ id, value: newNoteValue })}
/>
);
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.