זהו נושא דיון מלווה לערך המקורי שב־https://www.tocode.co.il/bundles/react/lessons/41-react-redux-lab
זהו נושא דיון מלווה לערך המקורי שב־https://www.tocode.co.il/bundles/react/lessons/41-react-redux-lab
1.) מצרפת את הפתרון שלי - אשמח להערות.
2.) בקומפוננטה של כתיבת הודעה חדשה שמרתי את הטקסט בסטייט של הקומפוננטה עצמה כיון שהמידע לא אמור להיות משותף בעוד קומפוננטות כל עוד לא לחצו על הכפתור, אז רק בעת לחיצה על הכפתור יצרתי ממנה הודעה, שהיא כן תשמר ב-store.
השאלה שלי היא האם במקרים בהם המידע לא אמור להיות משותף לכמה קומפוננטות, יש ענין לשמור אותו ב-store?
או שמקובל ברידקס שפקד מנהל גם סטייט משלו?
Redux:
loginReducer.js
import produce from 'immer';
const initialState = {
userName: "guest",
}
export default produce((state , action)=>{
switch(action.type) {
case 'SET_USERNAME':
state.userName = action.payload;
break;
}
}, initialState);
messagesReducer.js
import produce from 'immer';
import { nextId , deleteItemByID} from '../utils';
const initialState = {
messages:[
{id :0 , from: 'SYSTEM', text: 'Hello world'},
],
count: 1,
}
export default produce((state , action)=>{
switch(action.type) {
case 'RECEIVED_MESSAGE':
state.messages.push({id: nextId(state.messages) , ...action.payload});
state.count++;
break;
case 'DELETE_MESSAGE':
state.messages = deleteItemByID(state.messages , action.payload);
state.count--;
break;
}
}, initialState);
utils.js
export function nextId(items) {
return items.length ? Math.max(...items.map(item => item.id)) + 1 : 0;
}
export function deleteItemByID(items , id) {
return [...items].filter(item => item.id !== id);
}
actions.js
export function setMessage(message) {
return {type: 'RECEIVED_MESSAGE' , payload: message};
}
export function deleteMessage(id) {
return {type: 'DELETE_MESSAGE' , payload: id};
}
store.js
import { combineReducers, createStore } from 'redux';
import messages from './reducers/messagesReducer';
import login from './reducers/loginReducer';
const reducer = combineReducers({messages , login});
const store = createStore(reducer);
window.store = store;
export default store;
:Components
main.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import ChatApp from './chatApp';
import store from './redux/store';
import '../styles/main.scss';
const App = () => {
return (
<Provider store = {store}>
<ChatApp/>
</Provider>
)
}
ReactDOM.render(<App/>, document.querySelector('main'));
chatApp.js
import React from 'react';
import NewMessageForm , { NewMessageFormContainer } from './newMessageForm';
import IncomingMessages , { IncomingMessagesContainer } from './incomingMessages';
export default function ChatApp() {
return (
<div id="messages-page" className="page container">
<h1> Messages Page </h1>
<div className="page-content">
<NewMessageFormContainer>
<NewMessageForm/>
</NewMessageFormContainer>
<IncomingMessagesContainer>
<IncomingMessages/>
</IncomingMessagesContainer>
</div>
</div>
);
}
newMessageForm.js
import React, { useState } from 'react';
import { connect } from 'react-redux';
import { setMessage } from './redux/actions';
export function NewMessageFormContainer(props) {
return (
<div className="left container mt-5 mb-5">
<div className="row">
<div className="col-md-12">
<h4>Send Message</h4>
{props.children}
</div>
</div>
</div>
);
}
export default connect()(function NewMessageForm({dispatch}) {
const [from , setFrom] = useState('');
const [messageText , setMessageText] = useState('');
function sendMessage(e) {
e.preventDefault();
const message = {from: from , text: messageText};
dispatch(setMessage(message));
}
return (
<form id="new-message-form">
<div className="form-group">
<label htmlFor="msg-text" >Message Text:</label>
<input type="text" id="msg-text" name="message-text" className="form-control"
value={messageText} onInput={(e)=>setMessageText(e.target.value)}/>
</div>
<div className="form-group">
<label htmlFor="msg-to">From</label>
<input type="text" id="msg-to" name="message-to" className="form-control"
value={from} onInput={(e)=>setFrom(e.target.value)}/>
</div>
<input type="submit" value="Send" className="btn btn-primary" onClick={sendMessage}/>
</form>
);
})
incomingMessages.js
import React from 'react';
import { connect } from 'react-redux';
import MessagesCount from './messagesCount';
import { deleteMessage } from './redux/actions';
function mapStateToProps(state) {
return {
messages: state.messages.messages,
}
}
export function IncomingMessagesContainer(props) {
return(
<div className="right container mt-5 mb-5">
<div className="row">
<div className="col-md-12">
<h4>Incoming Messages</h4>
<MessagesCount/>
{props.children}
</div>
</div>
</div>
);
}
export default connect(mapStateToProps)(function IncomingMessages({messages , dispatch}) {
return (
<ul>
{messages.map(message=>(
<li key={message.id}>
<span className="from">{message.from}
<button className="btn btn-primary" onClick={()=>dispatch(deleteMessage(message.id))}>Delete</button>
</span>
<p>{message.text}</p>
</li>
))}
</ul>
);
});
messagesCount.js
import React from 'react';
import { connect } from 'react-redux';
function mapStateToProps(state) {
return {
count: state.messages.count,
}
}
export default connect(mapStateToProps)(function MesaagesCount({count}){
return (
<p>Count: {count}</p>
);
});
הי שאלה מצוינת והתשובה תלויה במה את בונה
אנחנו חושבים על המידע ששמור ב Redux Store כמו קופסת שימורים שאפשר להעביר ממקום למקום: לדוגמה יהיה קל מאוד לשמור את המידע הזה ב Local Storage, לשלוח אותו לשרת, לשמור רשימה של קופסאות כאלה כדי לעשות Undo, לשתף בין כמה גולשים בזמן אמת באמצעות Web Sockets וכו’
בבניית אפליקציה צריך כל הזמן לחשוב: איזה מידע הוא באמת פנימי שלי ואם אני אוסיף פונקציונאליות גלובאלית (כמו למשל סינכרון עם גולשים אחרים או שמירת כל המידע באפליקציה במכה אחת ל Local Storage) אז המידע הזה לא יהיה מסונכרן או שלא יישמר, ואיזה מידע הוא כן מספיק חשוב לי כדי לשמור אותו ב Redux
יש הרבה אנשים שיגידו שצריך לשמור הכל ב Redux כי ככה קל יותר לנהל את האפליקציה: אפשר לראות בכלי הפיתוח מה כל המידע שהאפליקציה עובדת עליו, אפשר לראות כל שינוי בזמן אמת, קל יותר לדבג וזה מתאים לציפיות המשתמשים.
מצד שני יש גם הרבה שיגידו שביישומים גדולים לשמור את הכל ב Redux הופך את הקוד למסורבל, קשה יותר לזהות איזה קומפוננטות משתמשות באיזה חלקים במידע ולאורך זמן ה Redux Store יהפוך למנופח כי אנחנו נפחד למחוק ממנו דברים (אפילו שאולי אף אחד כבר לא משתמש בהם).
יש גם סירבול בזה שכל פעולה שאני רוצה להוסיף למערכת צריך לעדכן את הקוד במספר קבצים.
בקיצור הבחירה שלך והיא לא בחירה קלה.