How do I use the scrollTo in react-springy-parallax?
I'm trying to use react-springy-parallax in a simple portfolio page, you can click to springy parallax scroll to the next page but I want to be able to use nav links as well, here is how the app is laid out:
App.js
class App extends React.Component {
constructor() {
super()
this.ref = 'parallax'
}
render() {
return (
<div>
<Parallax ref={this.ref} pages={4}>
<Parallax.Layer
offset={0}
speed={0.5}
onClick={() => this.refs.parallax.scrollTo(1)}
>
<Nav />
<Header />
</Parallax.Layer>
...
So the onClick here just scrolls to the next page, I want to be able to say in my Nav component click the About link and it will scroll +1 so scrollTo(1)
Here is the nav component:
Nav.js
class Nav extends React.Component {
render() {
return (
<div className="nav">
<ul className="links">
<li>
About
</li>
...
I did try importing the scrollTo named export from react-springy-parallax into the nav component but got an error in the Chrome dev console saying it's not a function
I'm now trying to use a click handler:
class Nav extends React.Component {
render() {
function handleClick(e) {
e.preventDefault()
console.log(e)
}
return (
<div className="nav">
<ul className="links">
<li>
<a
href="#"
onClick={handleClick}
>
About
</a>
</li>
...
But I don't know how to call back to App.js to call the scrollTo
Anyone have any ideas?
logged an issue with the repo owner and he was kind enough to give a few pointers:
Use contextTypes to access the scrollTo method from parallax
In the Nav component use:
Nav.contextTypes = { parallax: React.PropTypes.object }
This will allow you to use the scrollTo method
Something like:
class Nav extends React.Component {
render() {
return (
<div className="nav">
<ul className="links">
<li>
<a
href=""
onClick={this.context.parallax.scrollTo(0)}
>
Home
</a>
</li>
<li>
<a
href=""
onClick={this.context.parallax.scrollTo(1)}
>
About
</a>
</li>
You can also pass the function as a prop, like so:
class App extends React.Component {
constructor(props) {
super(props)
this.handleScroll = value => this.parallax && this.parallax.scrollTo(value)
}
render() {
return (
<div>
<Parallax
ref={ref => (this.parallax = ref)}
pages={4}
>
<Parallax.Layer
offset={0}
speed={0.5}
onClick={() => this.handleScroll(1)}
>
<Nav handleScroll={this.handleScroll} />
Then from the Nav component use props onClick={() => this.props.handleScroll(PAGE)} with PAGE being the page number you want to scroll to.
Related
i take my first steps on react.
I'm working on a gatsbyjs site, and i'm stuck on my nav component.
Following some tuts, I started creating a class component called Burger to show/hide the nav... setting props, state and bind.. no probs right now.
On another file i put my Nav functional components, using gatsbyjs "Link" component to manage links.
What i'm trying to do, is to change the state of the "Burger" component when I click on the link.
So I tried using the onClick event:
onClick={() => props.handleClick()}
it doesn't work and the error is: props.handleClick is not a function.
What im doing wrong?
thanks
// Burger.js
class Burger extends React.Component {
constructor(props) {
super(props);
this.state = { isOpen: false };
this.handleClick = this.handleClick.bind(this);
}
handleClick = () => {
this.setState({
isOpen: !this.state.isOpen,
});
this.state.isOpen
? document.body.classList.remove("nav-open")
: document.body.classList.add("nav-open");
};
render() {
const burgerState = this.state.isOpen ? open : "";
return (
<button className={`${burger} ${burgerState}`} onClick={this.handleClick}>
<span className={burger__label}>Menu</span>
<span className={burger__line}></span>
<span className={burger__line}></span>
<span className={burger__line}></span>
</button>
);
}
}
// Nav.js
const Nav = (props) => {
return (
<div className={nav__overlay}>
<div className={nav__wrap}>
<nav className={nav__primary}>
<ul>
<li>
<Link to='/' activeClassName={active} title='Home' onClick={() => props.handleClick()}>
Home
</Link>
</li>
<li>
<Link to='/about' activeClassName={active} title='About' onClick={() => props.handleClick()}>
About
</Link>
</li>
<li>
<Link to='/contact' activeClassName={active} title='Contact' onClick={() => props.handleClick()}>
Contact
</Link>
</li>
<li>
<Link to='/blog' activeClassName={active} title='Blog' onClick={() => props.handleClick()}>
Blog
</Link>
</li>
</ul>
</nav>
<div className='contact'>
<ul>
<li>aaa</li>
<li>aaa</li>
<li>aaa</li>
<li>aaa</li>
</ul>
</div>
</div>
</div>
);
};
Is the error with the Burger component or the Nav component? It's not clear how Nav.js or Burger.js are related or interact with one another. Another thing is that React doesn't care if the nav-open class is on the body or not, so if hooked up properly the function should be callable.
Given the error you provided — onClick={() => props.handleClick()} — it looks like this code is in the Nav component. Wherever you render the nav, you need to pass handleClick as a prop, e.g. <Nav handleClick={myFunction} />.
You can read more about props and how they work here: https://reactjs.org/docs/components-and-props.html
In my react app I have this child component that inherits data from its parent. However, it does not update the page with new data from the child component when a relevant anchor link is clicked.
Here's my build - https://suite-search-lk.surge.sh/result/369523
From the link above if you click on a suggested card h1 element it just updates the URL with the id but does not update the page with the relevant card data from that id.
Any idea how I can fix this? Do I have to force the component to re-update?
Parent component (Card Wrapper)
class CardWrapper extends React.Component {
constructor(props) {
super(props);
this.state = {
stories: []
};
}
componentDidMount() {
axios
.get(API)
// .then(response => console.log(response))
// get our stories array, check it and then change state to contain our stories
.then(data => {
let stories;
if (data.data.stories && data.data.stories) {
if (Array.isArray(data.data.stories)) {
stories = data.data.stories;
} else {
stories = [data.data.stories];
}
} else {
stories = [];
}
this.setState({
stories: stories
});
});
}
render() {
return (
<CardWrapperDiv>
<div className="headingWrapper">
<div className="heading"> Suggested for you</div>
</div>
<Cards>
{this.state.stories.map(story => {
return (
<Card
title={story.content.title}
img={story.content.img}
description={story.content.description}
deadline={story.content.deadline_date}
tags={story.content.tags}
key={story.id}
id={story.id}
/>
);
})}
</Cards>
</CardWrapperDiv>
);
}
}
export default CardWrapper;
Child component
class Card extends React.Component {
render() {
return (
<CardDiv>
<div className="cardbox">
<div className="cardDetails">
<div className="headlineText">
<Link to={`/result/${this.props.id}`}> {this.props.title} </Link>
</div>
<div className="headlineSub">Colombo, Sri Lanka</div>
<div className="headlineDes">{this.props.description}</div>
<div className="textRemain">
{" "}
Deadline date: {this.props.deadline}
</div>
<div className="buttonRow">
<button className="downloadBtn">Download</button>
<button className="viewBtn">View</button>
</div>
</div>
<div className="cardimgwrapper">
<div className="cardimg">
<img src={this.props.img} alt="some title" />
</div>
</div>
</div>
</CardDiv>
);
}
}
export default Card;
Sorry it seems I have figured this out using the following post - Can you force a React component to rerender without calling setState?
Although I'm not exactly sure if it's the best way to go about it.
Essentially I used an OnClick listener to run a function and forces a re-render of the entire component.
Hope this can help someone else :)
class Card extends React.Component {
handleButtonClick() {
this.forceUpdate();
}
render() {
return (
<CardDiv>
<div className="cardbox">
<div className="cardDetails">
<div className="headlineText">
<Link to={`/result/${this.props.id}`} onClick={this.handleButtonClick}> {this.props.title} </Link>
</div>
<div className="headlineSub">Colombo, Sri Lanka</div>
<div className="headlineDes">{this.props.description}</div>
<div className="textRemain">
{" "}
Deadline date: {this.props.deadline}
</div>
<div className="buttonRow">
<button className="downloadBtn">Download</button>
<button className="viewBtn">View</button>
</div>
</div>
<div className="cardimgwrapper">
<div className="cardimg">
<img src={this.props.img} alt="some title" />
</div>
</div>
</div>
</CardDiv>
);
}
}
export default Card;
U have to use ur child component as a pure component. PureComponent Update when ur props change.
class Card extends React.PureComponent {
handleButtonClick() {
this.forceUpdate();
}
render() {
return (
<CardDiv>
.....
.....
</CardDiv>
);
}
}
export default Card;
i am trying to get the Id of a student by clicking on the . But it's giving me error like TypeError: Cannot read property 'handleClick' of undefined. What's wrong in here.?? First atleast i need to get this handleClick function to be working.
This is my react code:
class Premontessori extends React.Component{
constructor(props){
super(props);
this.state={
post:[],
id:[]
};
this.handleClick = this.handleClick.bind(this);
}
handleClick(event) {
alert(event);
}
componentDidMount(){
let self = this;
axios.get('http://localhost:8080/list')
.then(function(data) {
//console.log(data);
self.setState({post:data.data});
self.setState({id:data.data})
});
}
render(){
console.log(this.state.id);
return(
<div className="w3-container">
<div className="w3-display-container">
<div className="w3-panel w3-border w3-yellow w3-padding-4 w3-xxlarge ">
<p >List Of Students</p>
<div className="w3-display-right w3-container">
<Link className="w3-btn-floating w3-yellow" style={{textDecoration:'none',float:'right'}} to="/createstudent">+</Link>
</div></div>
</div>
<ul className="w3-ul w3-card-4 w3-yellow"> {this.state.post.map(function(item, index) {
return (
<Link to="/displaylist" style={{textDecoration:'none'}} key={index} onClick={this.handleClick}>
<li className=" w3-hover-green w3-padding-16" >
<img src={require('./3.jpg')} className="w3-left w3-circle w3-margin-right " width="60px" height="auto" />
<span>{item.Firstname}</span><br/><br/>
</li>
</Link>
)}
)}
</ul>
</div>
);
}
}
export default Premontessori;
When you pass this.handleClick to Link, at the moment the event happens and function gets executed, the latter happens in context of instance of Link. And since Link component doesn't have handleClick prop, the operation fails.
Try to declare handleClick in a way it gets bound to current component at the time of instantiation:
handleClick = event => {
alert(event);
}
Or use Function#bind in your render function:
<Link onClick={this.handleClick.bind(this)} />
Link is already has an internal hanlder for clicking which is redirection to another Route , and it is a markup solution .
React router provides also a non-markup solution to redirect which is browserHistory.push.
Thus :
import {browserHistory} from 'react-router'
handleClick(event) {
event.preventDefault();
alert('you clicked me');
browserHistory.push('/displaylist');
}
<a style={{textDecoration:'none'}} key={index} onClick={this.handleClick}></a>
Instead of
import {Link} from 'react-router'
<Link to="/displaylist" style={{textDecoration:'none'}} key={index} onClick={this.handleClick}>
I am introducing my self in es6+, I have a hard time trying to pass a function props to another component.
This is my code:
class ProductList extends React.Component {
constructor(props) {
super(props);
this.onVote = this.handleProductUpVote.bind(this);
}
handleProductUpVote(productId) {
console.log(productId +" was upvoted.")
}
render() {
const products = Data.map((product) => {
return (
<Product
key={'product-'+product.id}
id={product.id}
title={product.title}
description={product.description}
url={product.url}
votes={product.votes}
submitter_avatar_url={product.submitter_avatar_url}
product_image_url={product.product_image_url}
onVote={this.handleProductUpVote}
/>
);
});
return (
<div className="ui items">
{products}
</div>
);
}
}
I want to pass the function onVote in this component(Product)
class Product extends React.Component {
handleUpVote() {
this.props.onVote(this.props.id).bind(this) /* the error is here, I am trying
to pass the id props, and invoke the onVote prop here */
}
render() {
return (
<div className="item">
<div className="image">
<img src={this.props.product_image_url} />
</div>
<div className="middle aligned content">
<div className="description">
<a onClick={this.handleUpVote}>
<i className="large caret up icon"/>
</a>
{this.props.votes}
</div>
<div className="description">
<a href={this.props.url}>
{this.props.title}
</a>
</div>
<div className="extra">
<span> Submitted by: </span>
<img
className="ui avatar image"
src={this.props.submitter_avatar_url}
/>
</div>
</div>
</div>
);
}
}
I have no problem with other props here. I am trying to invoke the function on handleUpVote, I used bind with it, but I can't make it work. Help?
You have to use bounded handleProductUpVote method when you pass it to Product component.
As you can see in constructor, you already bound it and assigned to this.onVote property.
There are 2 solutions:
You should use onVote={this.onVote} in render method.
Change the name of property onVote in constructor to this.handleProductUpVote. And you end up with this.handleProductUpVote = this.handleProductUpVote.bind(this) and leave assignment in render method (i.e. onVote={this.handleProductUpVote})
More info at http://reactkungfu.com/2015/07/why-and-how-to-bind-methods-in-your-react-component-classes/
Update:
And update your Product class:
class Product extends React.Component {
constructor(props) {
super(props);
this.handleUpVote = this.handleUpVote.bind(this);
}
handleUpVote() {
this.props.onVote(this.props.id)
}
// the render method
}
Remove the bind in handleUpVote() in your Product component and just invoke it like this.props.onVote(this.props.id);
ContentWithFooter has list of Card's. And each Card has a menu to flag or delete the Card (article). When the icon is clicked, I want to insert the menu (<DeleteFlagPost/>) for that Card only and not all the cards. Also after the menu is inserted, when clicked other than that menu, remove it from the menu component. How do I do that? I know this is a long list of HOW, but your help will really help me understand more. Thank you.
ContentWithFooter.js:
class ContentWithFooter extends React.Component {
render() {
return(
<div>
<Card/>
<Card/>
<Card/>
</div>
);
}
}
Card.js
class Card extends React.Component {
handleDeleteFlag() {
return(
// GET THE CLICKED OBJECT OF THIS CARD AND INSERT <DeleteFlagPost/>???
);
}
render() {
return(
<article class="article">
...
<div class="delete-flag-post-btn">
<i class="fa fa-ellipsis-v" aria-hidden="true" onClick={this.handleDeleteFlag}></i>
// INSERT THE <DeleteFlagPost/> here when clicked on I element...
</div>
...
...
</article>
);
}
}
Keep active card in the contentwithfooter
class ContentWithFooter extends React.Component {
updateMenuForCards(cardNumActive) {
this.setState({
cardNumActive
})
}
render() {
return(
<div>
<Card cardNumber= 0 showMenu={cardNumActive === 0} updateMenuForCards={updateMenuForCards}/>
<Card cardNumber= 1 showMenu={cardNumActive === 0} updateMenuForCards={updateMenuForCards}/>
<Card cardNumber= 2 showMenu={cardNumActive === 0} updateMenuForCards={updateMenuForCards}/>
</div>
);
}
}
class Card extends React.Component {
constructor() {
super(props);
}
handleDeleteFlag() {
this.props.updateMenuForCards(this.props.cardNumber)
}
renderDeleteFlag() {
if (this.props.showMenu) {
return (<DeleteFlag/>)
}
}
render() {
return(
<article class="article">
...
<div class="delete-flag-post-btn">
<i class="fa fa-ellipsis-v" aria-hidden="true" onClick={this.handleDeleteFlag}></i>
{this.renderDeleteFlag()}
</div>
...
...
</article>
);