Reputation: 759
I have a component with a button which I've changed to Link
component, since I need to scroll to a specific location on the webpage and set a component state.
The function works when there's a button
component used, and console.logs the needed value. However, when changing the button
to Link
, the value returned is undefined
.
The component:
import React, { Component } from "react";
import { Link } from "react-scroll";
class Scroll extends Component {
constructor(props) {
super(props);
this.state = {
value: ""
};
this.setValue = this.setValue.bind(this);
}
setValue = e => {
this.setState({ value: e.target.value });
console.log(this.state.value);
};
render() {
return (
<div>
<Link
value="feature"
onClick={this.setValue}
className="action-button"
to="signup-wrapper"
activeClass="active"
spy={true}
smooth={true}
offset={-100}
duration={200}
>
See Feature
</Link>
</div>
);
}
}
export default Scroll;
How to make it work so that the Link component both scrolls down to a specific element and successfully changes the state?
Upvotes: 0
Views: 2011
Reputation: 457
This answer requires your code to be refactored as I am using props instead of a value on the Link component, but I've created some boilerplate code with some comments so you know whats going on.
When I found out about hooks, my life was changed forever. I would strongly suggest watching the videos on youtube (90% Cleaner React With Hooks) from the guys at Facebook.
If you copy the code and remove the comments you will see how much cleaner pure components are instead of classes and standard components (although there are some exceptions to the rule).
Hope this helps, and happy to answer any questions
import React, { useState, useEffect } from "react";
import { Link } from "react-scroll";
export default function Scroll(props) {
// No contructor!
// This is a two pronged attack:
// - foo: This is the variable you want to declare
// - setFoo: This is the function that will update it.
// this saves a lot of time writing out this.setState({...})
const [foo, setFoo] = useState("");
// This is like an event listener, the code inside the function will be
// exectuted whenever the specified variables stored in [] changes -
// like ComponentDidUpdate with a filter.
useEffect(() => console.log(foo), [foo]);
// You can leave this array empty, and it will run the code inside on mount. Useful for fetching data from an API asyncrounously.
// Render function is not required, just return a jsx object
return (
<div>
<ScrollButton value="feature" text="See Feature" setFoo={setFoo} />
<div style={{ height: 5000 }} />
<div className="signup-wrapper">Content to scroll to</div>
</div>
);
}
function ScrollButton(props) {
return (
<Link
onClick={() => props.setFoo(props.value)}
className="action-button"
to="signup-wrapper"
activeClass="active"
spy={true}
smooth={true}
offset={-100}
duration={200}
>
{props.text}
</Link>
);
}
Upvotes: 1
Reputation: 6832
<Link>
component does not have a value like a button or an input. I guess you need to access the value
attribute using element.getAttribute :
setValue = e => {
this.setState({ value: e.target.getAttribute('value') });
};
Also, keep in mind setState
is async so using console.log()
just after will display the previous value, not the new one.
Upvotes: 1