How to link external url with button in Material UI? - reactjs

I'm pretty new to Material-UI and testing my web-app with localhost. Basically, I have created a button that will route to external url (www.google.ca for now) when the user clicks on it. For unknown reason, clicking a button routes to http://localhost:3001/www.google.ca instead of https://www.google.ca. Not sure what the problem is?
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import Card from '#material-ui/core/Card';
import CardActionArea from '#material-ui/core/CardActionArea';
import CardActions from '#material-ui/core/CardActions';
import CardContent from '#material-ui/core/CardContent';
import CardMedia from '#material-ui/core/CardMedia';
import Button from '#material-ui/core/Button';
import Typography from '#material-ui/core/Typography';
import Link from '#material-ui/core/Link';
import waterBottle from '../images/tom.jpg';
// All the code has been retrieved from https://material-ui.com/components/cards/#card
const useStyles = makeStyles({
root: {
maxWidth: 345,
},
media: {
height: 140,
},
});
export default function MembersInfo() {
const classes = useStyles();
return (
<Card className={classes.root}>
<CardActionArea>
<CardMedia
className={classes.media}
image={waterBottle}
title="Image"
/>
<CardContent>
<Typography gutterBottom variant="h5" component="h2">
Tom Wong
</Typography>
<Typography variant="body2" color="textSecondary" component="p">
Tom is a business administrative student at xxx university.
</Typography>
</CardContent>
</CardActionArea>
<CardActions>
<Button size="small" color="primary" href="www.google.ca" target="_blank" to = "/url">
Google
</Button>
</CardActions>
</Card>
);
}

In case anyone runs across this issue with using the Link component from Material UI - a few comments addressed some of the issues.
Additionally, make sure you're importing the Link correctly from material ui since they've updated their API. I tried using the API provided ('#mui/material/Link') but had to use their old API (#material-ui/core/Link) for it to work.
If the import is correct, this is the the code that will open up a new tab to google while you're developing using localhost:
<Link target="_blank" href="http://www.google.com" rel="noreferrer">
View Link
</Link>

Related

react movie app breaking when navigating movie detail page

i am creating a react movie app that uses an movie app API from rapid API. on home page everything is working perfectly and I am able to render all movies in the form of cards. i have set the app in such a way that when user clicks on movie card it should direct to Moviedetail page. for this i am using react-router-dom and everything is set up right. on clicking movie card it does navigate to Moviedetail page but nothing is being rendered and getting this error in browser console.
(Uncaught TypeError: Cannot read properties of undefined (reading 'length')
at Details (Details.js:18:1));
but if i comment Detail and MovieTrailers component in MovieDetails page and uncomment it then everything on MovieDetails page is rendered perfectly. again if i refresh the page it breaks again and i get the same browser console error.
import React, {useState, useEffect} from "react";
import {Box} from "#mui/material";
import {useParams} from "react-router-dom";
import MovieTrailers from "../components/MovieTrailers";
import Details from "../components/Details";
import {fetchData, options} from "../utils/fetchData";
function MovieDetails() {
const [movieDetailData, setMovieDetailData] = useState({});
const [movieTrailerData, setMovieTrailerData] = useState([]);
const {id} = useParams();
// console.log(id);
console.log(movieDetailData);
console.log(movieTrailerData);
useEffect(()=>{
const fetchMovieData = async ()=> {
const detailData = await fetchData(`https://movies-app1.p.rapidapi.com/api/movie/${id}`, options);
setMovieDetailData(detailData.result);
const trailerData = await fetchData(`https://movies-app1.p.rapidapi.com/api/trailers/${id}`, options);
setMovieTrailerData(trailerData.result);
}
fetchMovieData();
},[id]);
return(
<Box>
<Details
movieDetailData={movieDetailData}
/>
<MovieTrailers
movieTrailerData={movieTrailerData}
/>
</Box>)
}
export default MovieDetails;
////here is Details component
import React from "react";
import {Box, Stack, Typography, Chip} from "#mui/material";
function Details(props) {
const{image, titleOriginal, countries, genres, rating, release, description} = props.movieDetailData;
return <Stack direction="row" width="100%" sx={{backgroundColor:"#fff"}}>
<img className="movie-poster" src={image} alt="movie-poster"/>
<Stack p="50px" sx={{width:"60%"}}>
<Typography variant="h2" fontWeight="700">
{titleOriginal}
</Typography>
<Box pt="30px" sx={{display:"flex", gap:"30px"}}>
<Chip label={<Typography variant="h6" fontWeight="700">{`rating : ${rating}`}</Typography>} />
<Chip label={<Typography variant="h6" fontWeight="700">{`release: ${release}`}</Typography>} />
</Box>
<Typography variant="h6" pt="30px">
{description.length>600 ? description.substring(0, 601) : description}
</Typography>
<Box pt="30px" sx={{display:"flex", gap:"30px"}}>
<Chip label={<Typography variant="h6" fontWeight="700">{`genre : ${genres[0].name}`}</Typography>} />
<Chip label={<Typography variant="h6" fontWeight="700">{`origin : ${countries[0].name}`}</Typography>} />
</Box>
</Stack>
</Stack>
}
export default Details;
////here is MovieTrailer component
import React from "react";
import {Box, Stack, Typography} from "#mui/material";
import TrailerCard from "./TrailerCard";
import {nanoid} from "nanoid";
function MovieTrailers({movieTrailerData}) {
console.log(movieTrailerData);
return <Box p="30px">
<Typography variant="h4" pt="40px" pb="50px" fontWeight="700" m="auto">{`Watch ${movieTrailerData[0].title}`}
</Typography>
<Stack direction="row" justifyContent="space-between">
{(movieTrailerData.slice(0, 3)).map((trailer)=>(
<TrailerCard trailer={trailer}/>
))}
</Stack>
</Box>
}
export default MovieTrailers;
////here is TrailerCard component
import React from "react";
import {Box, Stack, Typography, Chip} from "#mui/material";
function TrailerCard({trailer}) {
const{thumbnail, ago, author, views, title, url, description} = trailer;
return <Box className="trailer-card" p="10px" backgroundColor="#fff" width="25%">
<Stack>
<a
className="movie-trailer-link"
href={url}
target="_blank"
rel="noreferrer">
<img className="movie-trailer-thumbnail" src={thumbnail} alt="movie-trailer"/>
<Typography pt="10px" variant="body1" fontWeight="700" >
{title}
</Typography>
<Stack paddingBlock="10px" direction="row" justifyContent="space-between" gap="10px" flexWrap="wrap">
<Chip label={`views: ${views}`} />
<Chip label={`ago: ${ago}`}/>
</Stack>
<Typography variant="subtitle2">{`YT: ${author.name}`}</Typography>
<Typography variant="body2" pb="20px">
{description}
</Typography>
</a>
</Stack>
</Box>
}
export default TrailerCard;
In your movie detail component, add a loading state initially set to true. Upon resolution of the API call in the useEffect, set the loading variable to false.
In the jsx, render the page data if loading is false else show a loader or something else
movieDetailData is an empty object before you fetch your data from backend. That's why you get an error.
First check if your props has suitable keys.
import React from "react";
import {Box, Stack, Typography, Chip} from "#mui/material";
function Details(props) {
if (Object.keys(props.movieDetailData).length == 0)
return null;
const{image, titleOriginal, countries, genres, rating, release, description} = props.movieDetailData;
// rest of your code
}

Unable to navigate to another web page using useNavigate in my ReactJS app

I am trying to navigate to a different web page using 'useNavigate'. I am getting the error message below and I don't quite understand what I am doing incorrectly. Please can someone advise?
import React from 'react';
import AppBar from '#mui/material/AppBar';
import Box from '#mui/material/Box';
import Toolbar from '#mui/material/Toolbar';
import Typography from '#mui/material/Typography';
import Button from '#mui/material/Button';
import IconButton from '#mui/material/IconButton';
import MenuIcon from '#mui/icons-material/Menu';
import { useNavigate } from 'react-router-dom';
import SendIcon from '#mui/icons-material/Send';
const Header = () => {
const SendMessage = () => {
console.log('Send message!');
const navigate = useNavigate();
navigate('/writeMessage');
}
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static">
<Toolbar>
<IconButton
size="large"
edge="start"
color="inherit"
aria-label="menu"
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
MyApp
</Typography>
<SendIcon sx={{ marginRight: "20px" }} onClick={SendMessage}>
</ SendIcon>
<Button variant="contained" >Connect Wallet</Button>
</Toolbar>
</AppBar>
</Box>
);
}
export default Header;
Console:
Uncaught Error: Invalid hook call. Hooks can only be called inside of the body of a function component. This could happen for one of the following reasons:
1. You might have mismatching versions of React and the renderer (such as React DOM)
2. You might be breaking the Rules of Hooks
3. You might have more than one copy of React in the same app
See https://reactjs.org/link/invalid-hook-call for tips about how to debug and fix this problem.
You are calling the useNavigate hook in a nested function. This breaks one of the Rules of Hooks, "Don’t call Hooks inside loops, conditions, or nested functions."
Move it to the component scope.
const Header = () => {
const navigate = useNavigate();
const SendMessage = () => {
console.log('Send message!');
navigate('/writeMessage');
};
...

AppBar component of material-ui package not working in my react js application

i am creating my first React Application (WebApp) and I have following issue.
I want a Navigation Bar and therefore I am using the AppBar component of the material-ui lib. I used the the example Simple App Bar explained on the official material-ui page.
If I compile and run the app I get the following result:
Why it doesn't look like the example on the website, althought I used the same code. What am I doing wrong?
Thanks in advance.
My js file:
import React from 'react';
import { makeStyles } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import Button from '#material-ui/core/Button';
import IconButton from '#material-ui/core/IconButton';
import MenuIcon from '#material-ui/icons/Menu';
const useStyles = makeStyles((theme) => ({
root: {
flexGrow: 1,
},
menuButton: {
marginRight: theme.spacing(2),
},
title: {
flexGrow: 1,
},
}));
export default function ButtonAppBar() {
const classes = useStyles();
return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<IconButton edge="start" className={classes.menuButton}
color="inherit" aria-label="menu">
<MenuIcon />
</IconButton>
<Typography variant="h6" className={classes.title}>
News
</Typography>
<Button color="inherit">Login</Button>
</Toolbar>
</AppBar>
</div>
);
}
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import reportWebVitals from './reportWebVitals';
import ButtonAppBar from './Components/ButtonAppBar';
ReactDOM.render(
<ButtonAppBar/>,
document.getElementById('root')
);
reportWebVitals();
UPDATE: I found the cause of my problem. I had an import of a component in my index.js file (which was not used). This component had a .css file attached which overruled the style of the AppBar.
I didn't know the .css file of a not used component has an impact, but I was wrong ^^
So as for why the color is not matching with documentation is because Material UI documentation uses it's own custom theme https://material-ui.com/customization/default-theme/, you can go to palette > Primary to get the exact color code.
As for why your nav bar looks like that I don't know I compiled the same code but got the desired result except the color, here's the code https://codesandbox.io/s/navbar-2xp1q?file=/demo.js

Menu Icon in App Bar

So I was wondering how I create a menu that pops up on the left side when someone clicks the menu icon on the app bar. Just to be clear I am talking about the appbar with buttons. Here's the code for it:
import React from 'react';
import PropTypes from 'prop-types';
import { withStyles } from '#material-ui/core/styles';
import AppBar from '#material-ui/core/AppBar';
import Toolbar from '#material-ui/core/Toolbar';
import Typography from '#material-ui/core/Typography';
import Button from '#material-ui/core/Button';
import IconButton from '#material-ui/core/IconButton';
import MenuIcon from '#material-ui/icons/Menu';
const styles = {
root: {
flexGrow: 1,
},
flex: {
flexGrow: 1,
},
menuButton: {
marginLeft: -12,
marginRight: 20,
},
};
function ButtonAppBar(props) {
const { classes } = props;
return (
<div className={classes.root}>
<AppBar position="static">
<Toolbar>
<IconButton className={classes.menuButton} color="inherit" aria-label="Menu">
<MenuIcon /> //I want a menu to pop up on the left-side when someone clicks this button
</IconButton>
<Typography variant="title" color="inherit" className={classes.flex}>
News
</Typography>
<Button color="inherit">Login</Button>
</Toolbar>
</AppBar>
</div>
);
}
ButtonAppBar.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(ButtonAppBar);
You can add multiple Icon in app bar on either side and should mention the action when the icon is clicked,try these steps and get menu or search icon in the app bar.
Source:
Add search and menu in app bar
you can have a parent component that is class based (which has all states and handlers baked in) then you can have a navigation component and sidebar component (both should be stateless component; based on usage of yours) then by clicking on a button on navigation you should change the corresponding state on the parent component; then you should chain the visibility of your sidebar component based on that state.
actually i just took a moment and created what you need here, just a simple example...
https://codesandbox.io/s/m86ko7vp
for adding animations you can use react-motion or react-spring

CardHeader is not rendering in React

I'm playing with React and material-ui, other stuff have worked but for some reason <CardHeader> is not getting rendered.
Below is the code
import React from "react";
import Card from "#material-ui/core/Card";
import CardHeader from "#material-ui/core/Card";
import CardContent from "#material-ui/core/Card";
import CardActions from "#material-ui/core/Card";
import Button from "#material-ui/core/Button";
import Paper from "#material-ui/core/Paper";
import Typography from "material-ui/Typography";
class PaperCard extends React.Component {
render() {
return (
<Card>
<CardHeader title="CaHellord" subheader="Test ME" />
<CardContent>
<Typography type="title">Word of the day</Typography>
<Typography type="headline" component="h2">
impediments
</Typography>
<Typography component="p">adjective</Typography>
</CardContent>
<CardActions>
<Button dense> Learn More </Button>
</CardActions>
</Card>
);
}
}
export default PaperCard;
Could someone point out the obvious which I have missed.
It's just the case of incorrect import.
Replace the import of CardHeader from
import CardHeader from "#material-ui/core/Card";
to
import CardHeader from "#material-ui/core/CardHeader";

Resources