如何将重定向 link 添加到 onclick Material ui 图标 - React
How to add redirect link to onclick Material ui icon - React
我在第 232 行向 VideocamOutlinedIcon
添加函数时遇到一些问题,我想在其中添加一个 onclick
将用户重定向到外部域 link另一个选项卡。我尝试了很多解决方案,但其中 none 有效。我尝试通过 react-router-dom
和 redirect
使用 Link
,但这些都不起作用。
我的代码:
import React, { useEffect, useState, useRef } from "react";
import { Avatar, IconButton } from "@material-ui/core";
import VideocamOutlinedIcon from '@material-ui/icons/VideocamOutlined';
import MoreVertIcon from "@material-ui/icons/MoreVert";
import SearchOutlined from "@material-ui/icons/SearchOutlined";
import InsertEmoticonIcon from "@material-ui/icons/InsertEmoticon";
import MicIcon from "@material-ui/icons/Mic";
import ArrowBackIcon from "@material-ui/icons/ArrowBack";
import db from "./firebase";
import firebase from "firebase";
import "./Chat.css";
import { Link, useParams, Redirect } from "react-router-dom";
import { useStateValue } from "./StateProvider";
import { actionTypes } from "./reducer";
import UseWindowDimensions from "./UseWindowDimensions";
import useSound from "use-sound";
import "emoji-mart/css/emoji-mart.css";
import { Picker } from "emoji-mart";
import Linkify from "react-linkify";
function Chat() {
const [seed, setSeed] = useState("");
const [input, setInput] = useState("");
const { roomId } = useParams();
const [roomName, setRoomName] = useState("false");
const [messages, setMessages] = useState([]);
const [toggler, setToggler] = useState(true);
const displayName = localStorage.getItem("displayName");
const [{ togglerState }, dispatch] = useStateValue();
const [{ photoURL }] = useStateValue();
const [emoji, setEmoji] = useState(false);
const [issendChecked, setIssendChecked] = useState(false);
const [datewise, setDateWise] = useState([]);
const [clientGMT, setClinetGMT] = useState("");
const [lastseenPhoto, setLastseen] = useState("");
const { width } = UseWindowDimensions();
var hour = 0,
extramin = 0,
minutes = 0,
hourly = 0,
GMTminutes = String(clientGMT).slice(4, 6),
scrl,
fix = 0;
const [playOn] = useSound(`${process.env.PUBLIC_URL}/send.mp3`, {
volume: 0.5,
});
const [playOff] = useSound(`${process.env.PUBLIC_URL}/send.mp3`, {
volume: 0.5,
});
const addEmoji = (e) => {
let emoji = e.native;
setInput(input + emoji);
};
const checkEmojiClose = () => {
if (emoji) {
setEmoji(false);
}
};
function getTimeZone() {
var offset = new Date().getTimezoneOffset(),
o = Math.abs(offset);
return (
(offset < 0 ? "+" : "-") +
("00" + Math.floor(o / 60)).slice(-2) +
":" +
("00" + (o % 60)).slice(-2)
);
}
useEffect(() => {
setClinetGMT(getTimeZone());
});
useEffect(() => {
setSeed(Math.floor(Math.random() * 5000));
if (roomId) {
db.collection("rooms")
.doc(roomId)
.onSnapshot((snapshot) => {
setRoomName(snapshot.data().name);
});
db.collection("rooms")
.doc(roomId)
.collection("messages")
.orderBy("timestamp", "asc")
.onSnapshot((snapshot) => {
setMessages(snapshot.docs.map((doc) => doc.data()));
});
}
}, [roomId]);
useEffect(() => {
setLastseen(messages[messages.length - 1]?.photoURL);
}, [messages]);
const sendMessage = (e) => {
e.preventDefault();
if (input.length > 0) {
db.collection("rooms")
.doc(roomId)
.collection("messages")
.add({
message: input,
name: displayName,
timestamp: firebase.firestore.FieldValue.serverTimestamp(),
photoURL: localStorage.getItem("photoURL"),
});
setIssendChecked(!issendChecked);
issendChecked ? playOff() : playOn();
setInput("");
}
};
let blankObj = {};
let TotalObj = [];
if (messages.length > 0) {
let checkDate = "";
let blankArray = [];
let dateArray = [];
messages.forEach(function (message, i) {
let messageDate = String(
new Date(message.timestamp?.toDate()).toUTCString()
).slice(5, 12);
if (dateArray.indexOf(messageDate) === -1) {
dateArray.push(messageDate);
}
});
var index = 0;
messages.forEach(function (message, i) {
let messageDate = String(
new Date(message.timestamp?.toDate()).toUTCString()
).slice(5, 12);
if (messageDate === dateArray[index] && i == messages.length - 1) {
blankArray.push({
messageData: message.message,
name: message.name,
timestamp: message.timestamp,
});
blankObj[dateArray[index]] = blankArray;
TotalObj.push(blankObj);
blankObj = {};
blankArray = [];
blankArray.push({
messageData: message.message,
name: message.name,
timestamp: message.timestamp,
});
index = index + 1;
} else if (messageDate == dateArray[index]) {
blankArray.push({
messageData: message.message,
name: message.name,
timestamp: message.timestamp,
});
} else {
blankObj[dateArray[index]] = blankArray;
TotalObj.push(blankObj);
blankObj = {};
blankArray = [];
blankArray.push({
messageData: message.message,
name: message.name,
timestamp: message.timestamp,
});
if (messageDate != dateArray[index] && i == messages.length - 1) {
blankObj[messageDate] = blankArray;
TotalObj.push(blankObj);
}
index = index + 1;
}
});
}
useEffect(() => {
setDateWise(TotalObj);
}, [messages]);
const messagesEndRef = useRef(null);
const scrollToBottom = () => {
if (messagesEndRef.current) {
messagesEndRef.current.scrollIntoView({ behavior: "smooth" });
}
};
useEffect(() => {
scrollToBottom();
});
useEffect(() => {
setToggler(!toggler);
}, [togglerState]);
useEffect(() => {
scrollToBottom();
}, [messages]);
const handleDrawerToggle = () => {
setToggler(!toggler);
dispatch({
type: actionTypes.SET_TOGGLER,
togglerState: togglerState + 1,
});
};
return (
<>
{width < 629 ? (
<div className={togglerState % 2 === 0 ? "chat" : "chat hide__chat"}>
<div className="chat__header">
<IconButton
color="inherit"
aria-label="open drawer"
edge="start"
onClick={handleDrawerToggle}
>
<ArrowBackIcon />
</IconButton>
<Avatar src={lastseenPhoto} />
<div className="chat__headerInfo">
<h3>{roomName}</h3>
<p className="header__lastSeen">
last seen{" "}
{messages.length !== 0
? messages[messages.length - 1].timestamp
?.toDate()
.toUTCString()
: "Loading"}
</p>
</div>
<div className="chat__headerRight">
<IconButton>
<SearchOutlined />
</IconButton>
<IconButton>
<VideocamOutlinedIcon />
</IconButton>
<IconButton>
<MoreVertIcon />
</IconButton>
</div>
</div>
export default Chat;
尝试
onClick={() => window.open('https://whosebug.com/')}
如果是外部 link,则不需要使用 react-router-dom。只需使用浏览器的功能 window.open 或 window.location.replace.
在您的情况下,在新标签页中打开:
window.open('https://www.google.com', '_blank');
那就是:
<IconButton>
<VideocamOutlinedIcon onClick={() => window.open('https://www.google.com', '_blank')} />
</IconButton>
不确定为什么其他人推荐 onClick
处理程序,以及为什么他们将处理程序添加到图标而不是包装 IconButton
。这不是正确的解决方案,只会给使用辅助技术的用户带来问题。
当你说你“想要添加一个 onclick
将用户重定向到另一个选项卡中的外部域 link”,你描述一个link。所以,当您尝试使用 react-router-dom
的 Link
时,您已经非常接近了。但是,如果您想让它尽可能简单且易于访问,您可以使用 a
元素和 target="_blank"
.
幸运的是,如果您在 Material UI 的 IconButton
组件上添加 href
属性,它会将其呈现为 a
元素,而不是button
,因此您可以使用以下内容:
<IconButton href="https://google.com" target="_blank" rel="noopener noreferrer">
<VideocamOutlinedIcon />
</IconButton>
它会呈现一个看起来像按钮的 link,辅助技术会将其宣布为 link。双赢.
<a
class="MuiButtonBase-root MuiIconButton-root"
tabindex="0"
aria-disabled="false"
href="https://google.com"
target="_blank"
rel="noopener noreferrer"
><span class="MuiIconButton-label"
><svg
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
aria-hidden="true"
>
<path
d="M15 8v8H5V8h10m1-2H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4V7c0-.55-.45-1-1-1z"
></path></svg></span
><span class="MuiTouchRipple-root"></span
></a>
我在第 232 行向 VideocamOutlinedIcon
添加函数时遇到一些问题,我想在其中添加一个 onclick
将用户重定向到外部域 link另一个选项卡。我尝试了很多解决方案,但其中 none 有效。我尝试通过 react-router-dom
和 redirect
使用 Link
,但这些都不起作用。
我的代码:
import React, { useEffect, useState, useRef } from "react";
import { Avatar, IconButton } from "@material-ui/core";
import VideocamOutlinedIcon from '@material-ui/icons/VideocamOutlined';
import MoreVertIcon from "@material-ui/icons/MoreVert";
import SearchOutlined from "@material-ui/icons/SearchOutlined";
import InsertEmoticonIcon from "@material-ui/icons/InsertEmoticon";
import MicIcon from "@material-ui/icons/Mic";
import ArrowBackIcon from "@material-ui/icons/ArrowBack";
import db from "./firebase";
import firebase from "firebase";
import "./Chat.css";
import { Link, useParams, Redirect } from "react-router-dom";
import { useStateValue } from "./StateProvider";
import { actionTypes } from "./reducer";
import UseWindowDimensions from "./UseWindowDimensions";
import useSound from "use-sound";
import "emoji-mart/css/emoji-mart.css";
import { Picker } from "emoji-mart";
import Linkify from "react-linkify";
function Chat() {
const [seed, setSeed] = useState("");
const [input, setInput] = useState("");
const { roomId } = useParams();
const [roomName, setRoomName] = useState("false");
const [messages, setMessages] = useState([]);
const [toggler, setToggler] = useState(true);
const displayName = localStorage.getItem("displayName");
const [{ togglerState }, dispatch] = useStateValue();
const [{ photoURL }] = useStateValue();
const [emoji, setEmoji] = useState(false);
const [issendChecked, setIssendChecked] = useState(false);
const [datewise, setDateWise] = useState([]);
const [clientGMT, setClinetGMT] = useState("");
const [lastseenPhoto, setLastseen] = useState("");
const { width } = UseWindowDimensions();
var hour = 0,
extramin = 0,
minutes = 0,
hourly = 0,
GMTminutes = String(clientGMT).slice(4, 6),
scrl,
fix = 0;
const [playOn] = useSound(`${process.env.PUBLIC_URL}/send.mp3`, {
volume: 0.5,
});
const [playOff] = useSound(`${process.env.PUBLIC_URL}/send.mp3`, {
volume: 0.5,
});
const addEmoji = (e) => {
let emoji = e.native;
setInput(input + emoji);
};
const checkEmojiClose = () => {
if (emoji) {
setEmoji(false);
}
};
function getTimeZone() {
var offset = new Date().getTimezoneOffset(),
o = Math.abs(offset);
return (
(offset < 0 ? "+" : "-") +
("00" + Math.floor(o / 60)).slice(-2) +
":" +
("00" + (o % 60)).slice(-2)
);
}
useEffect(() => {
setClinetGMT(getTimeZone());
});
useEffect(() => {
setSeed(Math.floor(Math.random() * 5000));
if (roomId) {
db.collection("rooms")
.doc(roomId)
.onSnapshot((snapshot) => {
setRoomName(snapshot.data().name);
});
db.collection("rooms")
.doc(roomId)
.collection("messages")
.orderBy("timestamp", "asc")
.onSnapshot((snapshot) => {
setMessages(snapshot.docs.map((doc) => doc.data()));
});
}
}, [roomId]);
useEffect(() => {
setLastseen(messages[messages.length - 1]?.photoURL);
}, [messages]);
const sendMessage = (e) => {
e.preventDefault();
if (input.length > 0) {
db.collection("rooms")
.doc(roomId)
.collection("messages")
.add({
message: input,
name: displayName,
timestamp: firebase.firestore.FieldValue.serverTimestamp(),
photoURL: localStorage.getItem("photoURL"),
});
setIssendChecked(!issendChecked);
issendChecked ? playOff() : playOn();
setInput("");
}
};
let blankObj = {};
let TotalObj = [];
if (messages.length > 0) {
let checkDate = "";
let blankArray = [];
let dateArray = [];
messages.forEach(function (message, i) {
let messageDate = String(
new Date(message.timestamp?.toDate()).toUTCString()
).slice(5, 12);
if (dateArray.indexOf(messageDate) === -1) {
dateArray.push(messageDate);
}
});
var index = 0;
messages.forEach(function (message, i) {
let messageDate = String(
new Date(message.timestamp?.toDate()).toUTCString()
).slice(5, 12);
if (messageDate === dateArray[index] && i == messages.length - 1) {
blankArray.push({
messageData: message.message,
name: message.name,
timestamp: message.timestamp,
});
blankObj[dateArray[index]] = blankArray;
TotalObj.push(blankObj);
blankObj = {};
blankArray = [];
blankArray.push({
messageData: message.message,
name: message.name,
timestamp: message.timestamp,
});
index = index + 1;
} else if (messageDate == dateArray[index]) {
blankArray.push({
messageData: message.message,
name: message.name,
timestamp: message.timestamp,
});
} else {
blankObj[dateArray[index]] = blankArray;
TotalObj.push(blankObj);
blankObj = {};
blankArray = [];
blankArray.push({
messageData: message.message,
name: message.name,
timestamp: message.timestamp,
});
if (messageDate != dateArray[index] && i == messages.length - 1) {
blankObj[messageDate] = blankArray;
TotalObj.push(blankObj);
}
index = index + 1;
}
});
}
useEffect(() => {
setDateWise(TotalObj);
}, [messages]);
const messagesEndRef = useRef(null);
const scrollToBottom = () => {
if (messagesEndRef.current) {
messagesEndRef.current.scrollIntoView({ behavior: "smooth" });
}
};
useEffect(() => {
scrollToBottom();
});
useEffect(() => {
setToggler(!toggler);
}, [togglerState]);
useEffect(() => {
scrollToBottom();
}, [messages]);
const handleDrawerToggle = () => {
setToggler(!toggler);
dispatch({
type: actionTypes.SET_TOGGLER,
togglerState: togglerState + 1,
});
};
return (
<>
{width < 629 ? (
<div className={togglerState % 2 === 0 ? "chat" : "chat hide__chat"}>
<div className="chat__header">
<IconButton
color="inherit"
aria-label="open drawer"
edge="start"
onClick={handleDrawerToggle}
>
<ArrowBackIcon />
</IconButton>
<Avatar src={lastseenPhoto} />
<div className="chat__headerInfo">
<h3>{roomName}</h3>
<p className="header__lastSeen">
last seen{" "}
{messages.length !== 0
? messages[messages.length - 1].timestamp
?.toDate()
.toUTCString()
: "Loading"}
</p>
</div>
<div className="chat__headerRight">
<IconButton>
<SearchOutlined />
</IconButton>
<IconButton>
<VideocamOutlinedIcon />
</IconButton>
<IconButton>
<MoreVertIcon />
</IconButton>
</div>
</div>
export default Chat;
尝试
onClick={() => window.open('https://whosebug.com/')}
如果是外部 link,则不需要使用 react-router-dom。只需使用浏览器的功能 window.open 或 window.location.replace.
在您的情况下,在新标签页中打开:
window.open('https://www.google.com', '_blank');
那就是:
<IconButton>
<VideocamOutlinedIcon onClick={() => window.open('https://www.google.com', '_blank')} />
</IconButton>
不确定为什么其他人推荐 onClick
处理程序,以及为什么他们将处理程序添加到图标而不是包装 IconButton
。这不是正确的解决方案,只会给使用辅助技术的用户带来问题。
当你说你“想要添加一个 onclick
将用户重定向到另一个选项卡中的外部域 link”,你描述一个link。所以,当您尝试使用 react-router-dom
的 Link
时,您已经非常接近了。但是,如果您想让它尽可能简单且易于访问,您可以使用 a
元素和 target="_blank"
.
幸运的是,如果您在 Material UI 的 IconButton
组件上添加 href
属性,它会将其呈现为 a
元素,而不是button
,因此您可以使用以下内容:
<IconButton href="https://google.com" target="_blank" rel="noopener noreferrer">
<VideocamOutlinedIcon />
</IconButton>
它会呈现一个看起来像按钮的 link,辅助技术会将其宣布为 link。双赢.
<a
class="MuiButtonBase-root MuiIconButton-root"
tabindex="0"
aria-disabled="false"
href="https://google.com"
target="_blank"
rel="noopener noreferrer"
><span class="MuiIconButton-label"
><svg
class="MuiSvgIcon-root"
focusable="false"
viewBox="0 0 24 24"
aria-hidden="true"
>
<path
d="M15 8v8H5V8h10m1-2H4c-.55 0-1 .45-1 1v10c0 .55.45 1 1 1h12c.55 0 1-.45 1-1v-3.5l4 4v-11l-4 4V7c0-.55-.45-1-1-1z"
></path></svg></span
><span class="MuiTouchRipple-root"></span
></a>