I want to change page when the div is clicked but when the page loads it automatically navigates to another page without clicking the div.
Why is the code navigating without clicking?
import React, { Component } from "react";
import { useNavigate } from "react-router-dom";
export function Homerouter(props) {
const navigate = useNavigate()
return(<Home navigate={navigate}></Home>)
}
export default class Home extends Component{
state = {categor: [{categ:"cat1", img: "https://teelindy.com/wp-content/uploads/2019/03/default_image.png"}, {categ:"cat2", img: "./imgs/notfound.png"}, {categ:"cat3", img: "./imgs/notfound.png"}, {categ:"cat4", img: "./imgs/notfound.png"}, {categ:"cat5", img: "./imgs/notfound.png"}, {categ:"cat6", img: "./imgs/notfound.png"}]}
linkto(name) {
//doing something else
this.props.navigate(name)
}
createelem() {
return(
<div className="cont text-center">
<div className="row row-cols-2 row-cols-lg-5 g-2 g-lg-3">
{this.state.categor.map((items, index) => {
return (
<div key={items.categ} className="col">
<div onClick={this.linkto("a")} className="card">
<img src={(items.img)} className="card-img-top" alt="..." />
<div className="card-body">
<h5 className="card-title">{items.categ}</h5>
</div>
</div>
</div>
);
})}
</div>
</div>
)
}
render() {
return(
<React.Fragment>
{this.createelem()}
</React.Fragment>
)
}
}
Cause you're invoking the function linkto immediately. Wrap this.linkto("a") as this:
onClick={() => this.linkto("a")}
Issue
You've a callback that is being immediately invoked when the component renders.
{this.state.categor.map((items) => {
return (
<div key={items.categ} className="col">
<div
onClick={this.linkto("a")} // <-- immediately called when rendered
className="card"
>
...
</div>
</div>
);
})}
Solution
You can either pass an anonymous callback function:
<div
onClick={() => this.linkto("a")}
className="card"
>
...
</div>
Or convert linkto to a curried function:
linkto(name) {
...
return e => {
// do anything with the click event e if necessary
this.props.navigate(name); // navigate
};
}
...
<div
onClick={this.linkto("a")}
className="card"
>
...
</div>
Or if there isn't any additional logic necessary directly call navigate in an anonymous callback:
<div
onClick={() => this.props.navigate("a")}
className="card"
>
...
</div>
Related
I'm creating a youtube clone using react js and i used this icon
import HomeIconfilled from '#mui/icons-material/Home';
import HomeIcon from '#mui/icons-material/HomeOutlined';
That looks like this HomeIconfilled
which gets rendered by calling this function
<Sidebariconfunc Icon={HomeIconfilled} Title="Home"/>
That takes 2 parameters and reder the icon
function Sidebariconfunc({Icon,Title}) {
return (
<div className='SidebarRow'>
<div className='Sidebar_Icon'>
<Icon/>
</div>
<div className='Slidebar_Title'>
{Title}
</div>
</div>
)
}
How can i chane the props name to HomeIcon when i click on the icon so that it changes to this this icon HomeIcon
Thamks !
function SidebarIcon({ActiveIcon, InactiveIcon, title, isActive}) {
return (
<div className='SidebarRow'>
<div className='Sidebar_Icon'>
{isActive ? <ActiveIcon/> : <InactiveIcon />
</div>
<div className='Slidebar_Title'>{Title}</div>
</div>
)
}
Usage:
const [isActive, setIsActive] = React.useState(false)
return (
<a onClick={() => setIsActive(!isActive)>
<SidebarIcon
ActiveIcon={HomeIconfilled}
InactiveIcon={HomeIcon}
title='Home'
isActive={isActive}
/>
</a>
)
I have a NextJS application, with the following page:
Page:
import Layout from "#/components/app/Layout";
import Sidebar from "#/components/app/Sidebar";
export default function SiteIndex() {
return (
<Layout>
<div className="flex">
<Sidebar />
<div className="m-5">
<iframe src="/page.htm"></iframe>
</div>
</div>
</Layout>
);
}
This page has an iframe, a parent Layout component, and one more component called Sidebar.
Parent Layout:
export default function Layout({ children }) {
return (
<div>
<div class="h-12 bg-gray-200 flex">
<div className="m-2 grow">Parent Layout</div>
<button className="bg-blue-500 text-white p-3">Reload iFrame Button</button>
</div>
<div>{children}</div>
</div>
)
}
Sidebar:
export default function Sidebar() {
return (
<div className="w-64 border border-r-100 m-5">
<div>Sidebar</div>
<button className="bg-blue-500 text-white p-3">Reload iFrame Button</button>
</div>
)
}
Both Layout and Sidebar have a button. I want to be able to reload the iframe on the press of any of those buttons. How can I achieve this in react/nextjs project? primarily I'm looking for the best way to reload an iFrame within reactjs.
Would it work for your application to add a key={keyValue} to the iframe? You can then set the value of that key whenever the button gets pressed. This should cause a re-render.
export default function SiteIndex() {
const [keyValue, setKeyValue] = useState(0);
return (
<Layout onButtonClick={() => setKeyValue(keyValue + 1)} >
<div className="flex">
<Sidebar onButtonClick={() => setKeyValue(keyValue + 1)} />
<div className="m-5">
<iframe src="/page.htm" key={keyValue}></iframe>
</div>
</div>
</Layout>
);
}
And in your component
I am a beginner in using the React JS framework. Based on the official React JS documentation, an example is given for changing the state of a component that has a connected hierarchy. But in my case this time I split the components for Header and Main separately.
index.js
ReactDOM.render(
<React.StrictMode>
<Header />
<Main />
</React.StrictMode>,
document.getElementById('root')
);
In the Header component I also have another sub component that functions to activate / deactivate the sidebar which is also a sub menu for the Main component.
Header.js
import { BtnSidebarOnClick } from './Sidebar';
const Header = () => {
return (
<header className="header">
<div className="header__logo">
<BtnSidebarOnClick />
<div className="header__logo_img">
<a className="link"
href="/">
<img src=""
alt="Schedule App" />
</a>
</div>
</div>
<nav className="header__nav">
...
</nav>
</header>
);
}
export default Header;
Main.js
import { Sidebar } from './Sidebar';
const Main = () => {
return (
<main className="main">
<Sidebar />
<div className="main__content">
...
</div>
</main>
);
}
export default Main;
Notice that the BtnSidebarOnClick and Sidebar components are not connected. In my case, this time I want to make the Sidebar component accept state to detect whether the button contained in the BtnSidebarOnClick component is clicked / not.
Sidebar.js
class BtnSidebarOnClick extends React.Component {
constructor(props) {
super(props);
this.state = { onClick: false };
}
handleClick() {
this.setState(state => ({ onClick: !state.onClick }));
}
render() {
return (
<div className="header__logo_btn">
<div className="button button--hover button--focus"
role="button"
tabIndex="0"
onClick={this.handleClick.bind(this)}>
<i className="material-icons">menu</i>
</div>
</div>
);
}
}
const Sidebar = () => {
return (
<div className="main__sidebar"> {/* set style if BtnSidebarOnClick clicked */}
<div className="main__sidebar_menu">
<div className="tag-link">
<a className="link link--hover link--focus link--active"
href="/">
<i className="material-icons">insert_drive_file</i>
<span className="link-title">Files</span>
</a>
</div>
</div>
</div>
);
}
export { Sidebar, BtnSidebarOnClick };
So how do you set these two components to receive the same state?
TLDR; You should pull out the button state into the parent and pass it into the children component.
By the way, it is a common way to have file App.js for your main Application file. In your case, it should be like this:
index.js
import App from './App';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
App.js
class App extends React.Component {
constructor(props) {
super(props);
this.state = { isClicked: false };
}
handleClick() {
this.setState(state => ({ isClicked: !state.isClicked }));
}
render() {
return (
<div>
<Header onClick={this.handleClick} /> // --> notice
<Main isClicked={this.state.isClicked} /> // --> notice
</div>
)
}
}
Header.js
import BtnSidebar from './BtnSidebar';
const Header = (props) => {
return (
<header className="header">
<div className="header__logo">
<BtnSidebar onClick={props.onClick} /> // --> notice
<div className="header__logo_img">
<a className="link"
href="/">
<img src=""
alt="Schedule App" />
</a>
</div>
</div>
<nav className="header__nav">
...
</nav>
</header>
);
}
Main.js
import Sidebar from './Sidebar';
const Main = (props) => {
return (
<main className="main">
<Sidebar isClicked={props.isClicked} /> // --> notice
<div className="main__content">
...
</div>
</main>
);
}
BtnSidebar.js
const BtnSidebar = (props) => {
return (
<div className="header__logo_btn">
<div className="button button--hover button--focus"
role="button"
tabIndex="0"
onClick={props.onClick} // --> notice
>
<i className="material-icons">menu</i>
</div>
</div>
);
}
Sidebar.js
const Sidebar = (props) => {
return (
<div
className={
props.isClicked ? 'main__sidebar-clicked' : 'main__sidebar' // --> notice
}
>
<div className="main__sidebar_menu">
<div className="tag-link">
<a className="link link--hover link--focus link--active"
href="/">
<i className="material-icons">insert_drive_file</i>
<span className="link-title">Files</span>
</a>
</div>
</div>
</div>
);
}
im having problems trying to use the onclick function as props it sais when i clicked TypeError: onClick is not a function
What can i do!
7 | <Card
8 | onClick={() => onClick(dish.id)}>
| ^ 9 |
it is my first time using this kind of components
import React from 'react';
import { Card, CardImg, CardImgOverlay,
CardTitle } from 'reactstrap';
function RenderMenuItem ({dish, onClick}) {
return (
<Card
onClick={() => onClick(dish.id)}>
<CardImg width="100%" src={dish.image} alt={dish.name} />
<CardImgOverlay>
<CardTitle>{dish.name}</CardTitle>
</CardImgOverlay>
</Card>
);
}
const Menu = (props) => {
const menu = props.dishes.map((dish) => {
return (
<div className="col-12 col-md-5 m-1" key={dish.id}>
<RenderMenuItem dish={dish} onClick={props.onClick} />
</div>
);
});
return (
<div className="container">
<div className="row">
{menu}
</div>
</div>
);
}
export default Menu;
Try to have default props to avoid run time errors.
const Menu = (props) => {
const menu = props.dishes.map((dish) => {
return (
<div className="col-12 col-md-5 m-1" key={dish.id}>
<RenderMenuItem dish={dish} onClick={props.onClick} />
</div>
);
});
return (
<div className="container">
<div className="row">{menu}</div>
</div>
);
};
Menu.defaultProps = {
dishes: [],
onClick: () => {},
};
You must now use Menu component by providing valid function. For example <Menu onClick={dishId => {/* Logic /*}}/>
I'm a bit new to React and I've been having some problems understanding the workarounds of certain methods that I've used in other languages.
The Problem:
What I was hoping to achieve is that whenever the user clicks a button, the app will render a new section displaying some variable values. What I did was that when the user clicked a button, an state changed, and let the new Component render, and I passed the data through its props.
The problem is, If I understand correctly, that I'm passing the old values when I create the component and not the actual/updated values that I want to render...
Let's say I have this following variables.
const user_data = {
pic_url: 'null',
followers: 'Loading...',
followings: 'Loading...',
nTweets: 'Loading...',
};
Those variables are going to change value whenever the user click a button.
This next block of code is what I use to render the next component where I want the new values.
const SomeComponent = props => {
const [resolved, setResolved] = useState({ display: false });
const displayValidation = props => {
setResolved({ ...resolved, display: !resolved.display });
};
function getData(username) {
const url = 'https://www.twitter.com/' + username;
getHTML(url)
.then(res => {
getUserData(res).then(res => {
user_data.followers = res.followers;
user_data.followings = res.followings;
user_data.nTweets = res.nTweets;
user_data.pic_url = res.pic_url;
console.log('Updated data:', user_data);
displayValidation();
});
})
.catch(function(error) {
console.error('Username was not found.');
});
}
const handleSubmit = event => {
event.preventDefault();
console.log('Resolving data...');
getData(user.username);
};
return (
<React.Fragment>
<Navbar />
<div className="container lg-padding">
<div className="row" id="getTracker">
<div className="col-sm-12 center">
<div className="card text-center hoverable">
<div className="card-body">
<div className="input-field">
<i className="material-icons prefix">account_circle</i>
<input
id="username"
type="text"
className="validate"
value={user.username}
onChange={handleChange}
/>
<label htmlFor="username">Enter a username to track</label>
</div>
<input
type="button"
onClick={handleSubmit}
value="Track"
className="btn-large blue darken-4 waves-effect waves-light"
/>
</div>
</div>
</div>
</div>
<div className="row">
<div className="col-sm-12">
**{resolved.display && <DisplayData type={1} data={user_data} />}**
</div>
</div>
</div>
<Footer />
</React.Fragment>
);
};
I want to see the new values, but it always render the first values that I passed when creating the component.
This is the component that I create
import React from 'react';
const DisplayData = props => {
const user = props.data;
console.log('Display', user);
switch (props.type) {
case 1: //Twitter
return (
<React.Fragment>
<div className="row lg-padding">
<div className="col-sm-12 lg-padding center">
<img
src={user.pic_url}
alt="profile_picture"
style={{ width: 50 + '%' }}
/>
</div>
<h2>{user.username}</h2>
</div>
<div className="row lg-padding">
<div className="col-sm-4">
<h4>Tweets: {user.nTweets}</h4>
</div>
<div className="col-sm-4">
<h4>Followers: {user.followers}</h4>
</div>
<div className="col-sm-4">
<h4>Followings: {user.followings}</h4>
</div>
</div>
</React.Fragment>
);
case 2: //Instagram
return <React.Fragment />;
default:
return (
<React.Fragment>
<div className="row lg-padding">
<div className="col-sm-12 lg-padding center">
<img
src={user.pic_url}
alt="profile_picture"
style={{ width: 50 + '%' }}
/>
<h2>Instagram_User</h2>
<h4>Posts: ND</h4>
<h4>Followers: ND</h4>
<h4>Followings: ND</h4>
</div>
</div>
</React.Fragment>
);
}
};
export default DisplayData;
How can I update the data in the component or render the component when the data is updated?
Maybe your user_data might to be a state object.
// Somecomponent ...
const [user_data, setUser_data] = useState({
pic_url: 'null',
followers: 'Loading...',
followings: 'Loading...',
nTweets: 'Loading...'
})
/* Rest of stuff */
const handleSubmit = async event => {
/*...*/
const userData = await getData(user.username)
setUser_data(userData)
}
// Then display the stated-stored user_data
<div className="col-sm-12">
**{resolved.display && <DisplayData type={1} data={user_data} />}**
</div>