Answer the question
In order to leave comments, you need to log in
How to hang a class on an event in React?
Hello.
There is a problem, when the mouse cursor hits an element with the old-chat class or the header class, then this element and the element with the header class are assigned an additional open-show class.
But, on the react it turned out to be not so easy for me personally, it hung quite well like that. I will be glad to help.
I'm stuck here
componentOpenChat() {
const openchat = document.querySelector(".old-chat");
openchat.addEventListener("onmouseover", (e) => {
e.preventDefault();
openchat.classList.add("open-show");
});
}
/* @flow */
import React from "react";
import io from "socket.io-client";
import { bindActionCreators } from "redux";
import { connect } from "react-redux";
import { compose, onlyUpdateForKeys } from "recompose";
import { stringify as b } from "rebem-classname";
import Scrollbars from "react-custom-scrollbars";
import { selectors as userSelectors } from "../user/logicBundle";
import { addMessage, deleteMessage, setMessages, addClanMessage, setClanMessages, sendMessage, sendClanMessage, apiBanChat, apiDeleteMessage, selectors as chatSelectors } from "../Chat/logicBundle";
import Message from "./Message";
import Coupon from "./Coupon";
import Ban from "../Chat/Ban";
import "./Chat.scss";
import type { UserType } from "../user/types";
const block = "old-chat";
class OldChat extends React.PureComponent {
constructor(props: Object) {
super(props);
this.onChatNewMessage = (message: Object) => {
const { actions } = this.props;
const { isClan } = this.state;
let isScroll = false;
if (
this.scrollbar.getScrollHeight() -
this.scrollbar.getScrollTop() -
this.scrollbar.getClientHeight() <=
30
) {
isScroll = true;
}
actions.addMessage(message);
if (!isClan && isScroll && this.scrollbar) {
this.scrollbar.scrollToBottom();
}
};
this.onChatDeleteMessage = (messageId: number) => {
const { actions } = this.props;
actions.deleteMessage(messageId);
};
this.onChatNewClanMessage = (message: Object) => {
const { actions } = this.props;
const { isClan } = this.state;
let isScroll = false;
if (
this.scrollbar.getScrollHeight() -
this.scrollbar.getScrollTop() -
this.scrollbar.getClientHeight() <=
30
) {
isScroll = true;
}
actions.addClanMessage(message);
if (isClan && isScroll && this.scrollbar) {
this.scrollbar.scrollToBottom();
}
}
};
state: {
isShow: boolean,
isClan: boolean,
message: string,
} = {
isShow: true,
isClan: false,
message: "",
};
componentDidMount() {
let { chat: socket } = window.socket;
if (!socket) {
window.socket.chat = io("/chat", window.socket.opts);
socket = window.socket.chat;
}
const { actions } = this.props;
const { isClan } = this.state;
socket.on("connect", () => {
socket.emit("chat:join", (messages: Object[]) => {
actions.setMessages(messages);
if (!isClan && this.scrollbar) {
this.scrollbar.scrollToBottom();
}
});
});
socket.on("chat:newMessage", this.onChatNewMessage);
socket.on("chat:deleteMessage", this.onChatDeleteMessage);
}
componentWillReceiveProps(nextProps) {
const { chat: socket } = window.socket;
const { user, actions } = nextProps;
if (user.id && user.id !== this.props.user.id && user.clan) {
socket.emit("chat:clanJoin", (messages: Object[]) => {
actions.setClanMessages(messages);
if (this.state.isClan && this.scrollbar) {
this.scrollbar.scrollToBottom();
}
});
socket.on("chat:newClanMessage", this.onChatNewClanMessage);
}
}
componentWillUnmount() {
const { chat: socket } = window.socket;
socket.off("chat:newMessage", this.onChatNewMessage);
socket.off("chat:deleteMessage", this.onChatDeleteMessage);
socket.off("chat:newClanMessage", this.onChatNewClanMessage);
}
componentOpenChat() {
const openchat = document.querySelector(".old-chat");
openchat.addEventListener("onmouseover", (e) => {
e.preventDefault();
openchat.classList.add("open-show");
});
}
onChatNewMessage: Function;
onChatDeleteMessage: Function;
onChatNewClanMessage: Function;
props: {
handleToggle: Function,
user: UserType,
messages: Object[],
clanMessages: Object[],
actions: Object,
};
handleChange = (e: Object) => {
this.setState({ [e.target.name]: e.target.value });
};
handleSendMessage = (e: Object) => {
e.preventDefault();
const { isClan, message } = this.state;
if (!isClan) {
this.props.actions.sendMessage(message);
} else {
this.props.actions.sendClanMessage(message);
}
this.setState({ message: "" });
};
handleToggle = (force: boolean, isClan: boolean) => () => {
this.setState({
isShow: force || !this.state.isShow,
isClan,
});
setTimeout(() => this.scrollbar && this.scrollbar.scrollToBottom(), 100);
};
render() {
const { user, messages: _messages, clanMessages, actions } = this.props;
const { isShow, isClan, message } = this.state;
const messages = !isClan ? _messages : clanMessages;
return (
<aside className={b({ block })}>
<div className={b({ block, elem: "container", mods: { show: isShow } })}>
<div className={b({ block, elem: "head" })}>
<span>{!isClan ? "Чат" : "Чат клана"}</span>
<div className={"navbar__online"}>
<i className="fa fa-users" />
<div>Online: </div>
</div>
<button className={b({ block, elem: "item" })} onClick={this.handleToggle(true, false)}>
<i className="fa fa-comments" />
</button>
{user.clan && (
<button className={b({ block, elem: "item" })} onClick={this.handleToggle(true, true)}>
<i className="fa fa-users" />
</button>
)}
<button className={b({ block, elem: "hide-btn" })} onClick={this.handleToggle(false, isClan)}>
<i className="fa fa-double-chevron-right" />
</button>
</div>
<div className={b({ block, elem: "messages" })}>
<Scrollbars
renderTrackHorizontal={() => <div style={{ display: "none" }} />}
ref={scrollbar => { this.scrollbar = scrollbar; }}
>
<div className={b({ block, elem: "messages-container" })}>
{messages.map((_message: Object) => {
if (_message.is_coupon) {
return (
<Coupon key={_message.id} message={_message.message} />
);
}
if (_message.is_ban) {
return (
<Ban key={_message.id} message={_message.message} />
);
}
return (
<Message
key={_message.id}
id={_message.id}
user={_message.user}
message={_message.message}
showControls={!isClan && (user.is_admin || user.is_moderator)}
banChat={actions.apiBanChat}
deleteMessage={actions.apiDeleteMessage}
/>
);
})}
</div>
</Scrollbars>
</div>
<form className={b({ block, elem: "send" })} onSubmit={this.handleSendMessage}>
<input
className={b({ block, elem: "send-input" })}
type="text"
placeholder="Введите сообщение..."
name="message"
value={message}
onChange={this.handleChange}
/>
<button className={b({ block, elem: "send-btn" })} type="submit">
<i className="fa fa-comment-o" />
</button>
</form>
</div>
<div className={b({ block, elem: "bar" })}>
<button className={b({ block, elem: "item" })} onClick={this.handleToggle(true, false)}>
<i className="fa fa-comments" />
</button>
{user.clan && (
<button className={b({ block, elem: "item" })} onClick={this.handleToggle(true, true)}>
<i className="fa fa-users" />
</button>
)}
</div>
</aside>
);
}
}
export const enhance = compose(
connect(
state => ({
user: userSelectors.getUser(state),
messages: chatSelectors.getMessages(state),
clanMessages: chatSelectors.getClanMessages(state),
}),
dispatch => ({
actions: bindActionCreators({
addMessage,
deleteMessage,
setMessages,
addClanMessage,
setClanMessages,
sendMessage,
sendClanMessage,
apiBanChat,
apiDeleteMessage,
}, dispatch),
})
),
onlyUpdateForKeys(["user", "messages", "clanMessages"])
);
export default enhance(OldChat);
Answer the question
In order to leave comments, you need to log in
best through css, but if through react, then update the state on the onMouseOver/Out event, and re-render with a new class
https://codesandbox.io/s/pensive-dubinsky-e7xt7
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question