Darren
Darren

Reputation: 2290

Select onChange link to value - ReactJS

How can I link to a value when selected onChange in a select box?

Looking to implement a select menu into ReactJS that links to the value onChange.

render() {
   return (
      <select onChange={() => {if (this.value) window.location.href=this.value}}>
        <option value="">Please select</option>
        {pages.map(({ node: page })=> (
          <option key={page.id} value="{page.slug}">{page.title}</option>
        ))}
      </select>
    );
}

This is getting the value (I believe) but I keep getting the error of Cannot read property 'value' of undefined

I have tried following the documents here as suggested in some answers yet I have not been able to get this working with my current code - see as follows the full Page.js

import React from 'react'
import Helmet from 'react-helmet'
import styled from 'styled-components'
import config from '../utils/siteConfig'

const PageCompany = ({data}) => {

  const {title,slug} = data.contentfulCompanyPage;
  const pages = data.allContentfulCompanyPage.edges;

  return(
    <Wrapper>
      <CompanyMenu>
        <div>
          <select onChange={() => {if (this.value) window.location.href=this.value}}>
            <option value="">Please select</option>
            {pages.map(({ node: page })=> (
              <option key={page.id} value="{page.slug}">{page.title}</option>
            ))}   
          </select>
        </div>
      </CompanyMenu>
    </Wrapper>
  )
}

export const companyQuery = graphql`
  query companyQuery($slug: String!) {
    contentfulCompanyPage(slug: {eq: $slug}) {
      title
      slug
      keywords
      description
      heroBg {
        sizes(maxWidth: 1500) {
          src
        }
      }
    }
    allContentfulCompanyPage(sort: {fields: [menuOrder], order: ASC}) {
      edges {
        node {
          id
          title
          slug
        }
      }
    }
  }
`

export default PageCompany

Upvotes: 1

Views: 12941

Answers (2)

Aaqib
Aaqib

Reputation: 10350

Instead of making use of Global window.location property you can make a separate method handleChange like :

constructor(props) {
    super(props);
    this.state = { }; // initialise state 

 // Make sure to bind handleChange or you can make use of arrow function

   this.handleChange = this.handleChange.bind(this);
  }

  handleChange(e) {
    const targetValue = e.target.value;
// Then you can do whatever you want to do with the value 
    this.setState({
      [name]: targetValue
    });

EDIT : In order to make use of constructor make sure you are defining components using class syntax like:

    import React , { Component } from 'react';

    class PageCompany extends Component { 
        constructor(props) {
          super(props);
          this.state = { }; // initialise state 
         this.handleChange = this.handleChange.bind(this);
     }

    // Make sure class has a render method 

    render () {
     return ()  
    }
 }

And inside your <Select> You can reference it to handleChange

<select onChange={this.handleChange}>

You can read more about onChange Here

Upvotes: 1

cameck
cameck

Reputation: 2098

You need to pass the event param and then grab the value from the target of that event e.g.

onChange={(event) => this.setState({value: event.target.value})}

There's a great example here.
Full code excerpt from linked docs:

class NameForm extends React.Component {
  constructor(props) {
    super(props);
    this.state = {value: ''};

    this.handleChange = this.handleChange.bind(this);
    this.handleSubmit = this.handleSubmit.bind(this);
  }

  handleChange(event) {
    this.setState({value: event.target.value});
  }

  handleSubmit(event) {
    alert('A name was submitted: ' + this.state.value);
    event.preventDefault();
  }

  render() {
    return (
      <form onSubmit={this.handleSubmit}>
        <label>
          Name:
          <input type="text" value={this.state.value} onChange={this.handleChange} />
        </label>
        <input type="submit" value="Submit" />
      </form>
    );
  }
}

Upvotes: 0

Related Questions