#reactjs
#reactjs
Вопрос:
Пожалуйста, помогите, я новичок в react. Я пытаюсь создать простое приложение для обмена сообщениями.
Я хочу, чтобы компонент MessageForm слегка перерисовывался при обновлении [сообщений]. он делает это, но не останавливается, даже если обновления нет.
И я знаю это, потому что, когда я проверяю свои инструменты redux dev, я продолжаю видеть одно действие повторно
const MessageForm = ({ getMessages, addMessages, deleteMessages, messages, roomId,}) => {
useEffect(() => {
getMessages(roomId);
scrollToBottom();
}, [messages]);
const [formData, setFormData] = useState({
text: "",
});
const { text } = formData;
let messagesEnd;
const scrollToBottom = () => {
messagesEnd.scrollIntoView({ behavior: "smooth" });
};
const onChange = (e) =>
setFormData({ ...formData, [e.target.name]: e.target.value });
const onSubmit = (e) => {
e.preventDefault();
addMessages(text, roomId);
setFormData({ text: "" });
};
let user = JSON.parse(localStorage.getItem("user"));
let messageList = messages.messages.map((message) => {
return message.user === user._id ? (
<div className="row">
<div className="container darker col-6" key={message._id}>
<div className="username"> {message.name}</div>
<Avatar
size="50"
round={true}
src={message.avatar}
className="right"
/>
<p>{message.text.toString()}</p>
<span className="time-left">
{moments(message.createdAt).format("LLL")}
</span>
<span className="time-right">
<Icon
onClick={() => {
deleteMessages(message._id);
}}
name="trash alternate"
className="trashCan"
/>
</span>
</div>
</div>
) : (
<div className="row justify-content-end">
<div className="container darker senders col-6 " key={message._id}>
<div className="username"> {message.name}</div>
<Avatar
size="50"
round={true}
src={message.avatar}
className="right"
/>
<p>{message.text.toString()}</p>
<span className="time-left">
{moments(message.createdAt).format("LLL")}
</span>
<span className="time-right">
<Icon
onClick={() => {
deleteMessages(message._id);
}}
name="trash alternate"
className="trashCan"
/>
</span>
</div>
</div>
);
});
return (
<div className="messageArea">
<div className="textarea">
{messageList}
<div
style={{ float: "left", clear: "both" }}
ref={(el) => {
messagesEnd = el;
}}
></div>
</div>
<form className="row inputBox" onSubmit={onSubmit}>
<div className="col-10">
<input
type="text"
className="form-control"
placeholder="Enter Message"
aria-label="Enter Message"
aria-describedby="basic-addon2"
id="text"
value={text}
name="text"
onChange={onChange}
/>
</div>
<div className="col-2">
<button className="btn btn-outline-secondary" type="submit">
Send
</button>
</div>
</form>
</div>
);
};
const mapDispatchToProps = (dispatch) => ({
addMessages: (text, roomId) => dispatch(addMessages(text, roomId)),
getMessages: (roomId) => dispatch(getMessages(roomId)),
deleteMessages: (id) => dispatch(deleteMessages(id)),
});
const mapStateToProps = (state, props) => ({
messages: state.messages,
roomId: props.location.state.roomId,
});
export default connect(mapStateToProps, mapDispatchToProps)(MessageForm);
Ответ №1:
Есть две проблемы.
- Вы вызываете
getMessages
метод, который, вероятно, обновляетmessages
оба реквизита, и если один из них изменится, обновится весь компонент. useEffect не контролирует родительский компонент, поэтому каждый раз, когда родительский компонент обновляется, дочерние элементы будут обновляться. - Вторая проблема заключается в том, что вы вызываете метод,
useEffect
который перезагружаетсяmessages
, затем он снова вызываетсяuseEffect
.
Я бы исправил это, getMessages
выйдя из этого компонента, или я бы вставил оператор if, useEffect
чтобы узнать, нужно ли вам вызывать getMessages
.
Ответ №2:
Добавляя к ответу @nzajt, возможно, вам не нужно использовать «сообщения» в качестве зависимости от вашего useEffect. Просто рассматривайте его как componentDidMount
useEffect(() => {
getMessages(roomId);
scrollToBottom();
}, []);
Таким образом, он не будет перерисовываться бесконечно, но вы не получите больше обновлений после первого рендеринга.
Если вы ищете что-то в режиме реального времени, взгляните на что-нибудь с помощью websockets, настройте прослушиватели или, возможно, запустите функцию GetMessages каждые несколько секунд.