Ruham
Ruham

Reputation: 759

React Link onClick setState returns undefined

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

Answers (2)

Simon Curtis
Simon Curtis

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

sebastienbarbier
sebastienbarbier

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

Related Questions