admin管理员组

文章数量:1294329

I have the following:

import React from 'react';
import {render} from 'react-dom';

class TShirt extends React.Component {
    render () {
        return <div className="thsirt">{this.props.name}</div>;
    }
}

class FirstName extends React.Component {
    propTypes: {
        name: React.PropTypes.string.isRequired
    }
    constructor(props) {
        super(props);
        this.state = {
            submitted: false
        };
    }
    getName () {
        var name = this.refs.firstName.value;
        this.setState(function() {
          this.props.action(name);
        });
    }
    handleSubmit (e) {
        e.preventDefault();
        this.setState({ submitted: true }, function() {
            this.props.actionNav('color');
        });
    }
    render () {
        if(!this.state.submitted){
            return (
                <div>
                    <h2>tell us your first name</h2>
                    <form>
                        <input 
                            type="text"
                            ref="firstName"
                            onChange={this.getName.bind(this)}
                        />
                        <div className="buttons-wrapper">
                            <a href="#">back</a>
                            <button onClick={this.handleSubmit.bind(this)}>continue</button>
                        </div>
                    </form>
                </div>
            );
        }
        else {
             return <PickColor color={this.props.colorVal} />;
        }
    }
}

class Link extends React.Component {
    setActiveClass () {
        if(this.props.el == this.props.activeClass){
            return 'active';
        }
    }
    render () {
        var active = this.setActiveClass();
        return (
            <li className={active}>{this.props.el}</li>
        );
    }
}

class Nav extends React.Component {
    render () {
        var links = ['name', 'color', 'design', 'share'],
            newLinks = [],
            that = this;
        links.forEach(function(el){
            newLinks.push(<Link activeClass={that.props.active} key={el} el={el} />);
        });
        return (
            <ul>
                {newLinks}
            </ul>
        );
    }
}

class PickColor extends React.Component {
    getColorValue(event) {
        console.log(event.target.getAttribute("data-color"));
        console.log(this);
        //this.props.color(event.target.getAttribute("data-color"));
    }
    render () {
        var colors = ['red', 'purple', 'yellow', 'green', 'blue'],
            colorsLink = [],
            that = this;

        colors.forEach(function(el){
            colorsLink.push(<li data-color={el} key={el} onClick={that.getColorValue} ref={el}>{el}</li>);
        });

        return (
            <ul>
                {colorsLink}
            </ul>
        );
    }

}

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            name: '',
            color: '',
            active: ''
        };
        this.getName = this.getName.bind(this);
        this.setActiveNav = this.setActiveNav.bind(this);
        this.setColor = this.setColor.bind(this);
    }
    getName (tshirt) {
        this.setState({ name:tshirt })
    }
    setActiveNav (active) {
        this.setState({ active:active })
    }
    setColor (color) {
        this.setState({ color:color })
    }
    render () {
        return (
            <section className={this.state.color}>
                <Nav active={this.state.active} />
                <TShirt name={this.state.name} />
                <FirstName name={this.state.name} action={this.getName} actionNav={this.setActiveNav} colorVal={this.setColor} />
            </section>
        );
    }
}

render(<App/>, document.getElementById('app'));

Inside the "PickColor" ponent I am trying to do this:

getColorValue(event) {
    console.log(event.target.getAttribute("data-color"));
    console.log(this);
    //this.props.colorVal(event.target.getAttribute("data-color"));
}

however this is returning null on click so I can't go ahead ans use:

this.props.colorVal

I have the following:

import React from 'react';
import {render} from 'react-dom';

class TShirt extends React.Component {
    render () {
        return <div className="thsirt">{this.props.name}</div>;
    }
}

class FirstName extends React.Component {
    propTypes: {
        name: React.PropTypes.string.isRequired
    }
    constructor(props) {
        super(props);
        this.state = {
            submitted: false
        };
    }
    getName () {
        var name = this.refs.firstName.value;
        this.setState(function() {
          this.props.action(name);
        });
    }
    handleSubmit (e) {
        e.preventDefault();
        this.setState({ submitted: true }, function() {
            this.props.actionNav('color');
        });
    }
    render () {
        if(!this.state.submitted){
            return (
                <div>
                    <h2>tell us your first name</h2>
                    <form>
                        <input 
                            type="text"
                            ref="firstName"
                            onChange={this.getName.bind(this)}
                        />
                        <div className="buttons-wrapper">
                            <a href="#">back</a>
                            <button onClick={this.handleSubmit.bind(this)}>continue</button>
                        </div>
                    </form>
                </div>
            );
        }
        else {
             return <PickColor color={this.props.colorVal} />;
        }
    }
}

class Link extends React.Component {
    setActiveClass () {
        if(this.props.el == this.props.activeClass){
            return 'active';
        }
    }
    render () {
        var active = this.setActiveClass();
        return (
            <li className={active}>{this.props.el}</li>
        );
    }
}

class Nav extends React.Component {
    render () {
        var links = ['name', 'color', 'design', 'share'],
            newLinks = [],
            that = this;
        links.forEach(function(el){
            newLinks.push(<Link activeClass={that.props.active} key={el} el={el} />);
        });
        return (
            <ul>
                {newLinks}
            </ul>
        );
    }
}

class PickColor extends React.Component {
    getColorValue(event) {
        console.log(event.target.getAttribute("data-color"));
        console.log(this);
        //this.props.color(event.target.getAttribute("data-color"));
    }
    render () {
        var colors = ['red', 'purple', 'yellow', 'green', 'blue'],
            colorsLink = [],
            that = this;

        colors.forEach(function(el){
            colorsLink.push(<li data-color={el} key={el} onClick={that.getColorValue} ref={el}>{el}</li>);
        });

        return (
            <ul>
                {colorsLink}
            </ul>
        );
    }

}

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            name: '',
            color: '',
            active: ''
        };
        this.getName = this.getName.bind(this);
        this.setActiveNav = this.setActiveNav.bind(this);
        this.setColor = this.setColor.bind(this);
    }
    getName (tshirt) {
        this.setState({ name:tshirt })
    }
    setActiveNav (active) {
        this.setState({ active:active })
    }
    setColor (color) {
        this.setState({ color:color })
    }
    render () {
        return (
            <section className={this.state.color}>
                <Nav active={this.state.active} />
                <TShirt name={this.state.name} />
                <FirstName name={this.state.name} action={this.getName} actionNav={this.setActiveNav} colorVal={this.setColor} />
            </section>
        );
    }
}

render(<App/>, document.getElementById('app'));

Inside the "PickColor" ponent I am trying to do this:

getColorValue(event) {
    console.log(event.target.getAttribute("data-color"));
    console.log(this);
    //this.props.colorVal(event.target.getAttribute("data-color"));
}

however this is returning null on click so I can't go ahead ans use:

this.props.colorVal

Share asked Jan 10, 2017 at 12:30 AessandroAessandro 5,77121 gold badges72 silver badges146 bronze badges 2
  • Did you try this.props.color instead? When you render your PickColor you are constructing it with different prop name: return <PickColor color={this.props.colorVal} />;, you are using color, not colorVal there. – Facundo La Rocca Commented Jan 10, 2017 at 12:40
  • the problem is around this key word – Aessandro Commented Jan 10, 2017 at 12:42
Add a ment  | 

3 Answers 3

Reset to default 2

The solution was here:

class PickColor extends React.Component {
    getColorValue(event) {
        console.log(event.target.getAttribute("data-color"));
        this.props.color(event.target.getAttribute("data-color"));
    }
    render () {
        var colors = ['red', 'purple', 'yellow', 'green', 'blue'],
            colorsLink = [],
            that = this;

        colors.forEach(function(el){
            colorsLink.push(<li data-color={el} key={el} onClick={that.getColorValue.bind(that)} ref={el}>{el}</li>);
        });

        return (
            <ul>
                {colorsLink}
            </ul>
        );
    }
}

I had to bind "that" to the onClick inside the forEach loop

Issue is in this line:

onClick={that.getColorValue}

You forgot to bind the correct this (class context) with onClick event handler function because of that this.props is not accessible in getColorValue function.


Solutions:

Multiple Solutions are possible, use any one (all these changes are for PickColor ponent):

1- Inline binding of click handler:

onClick = { that.getColorValue.bind(this) }

2- Bind the method in the constructor:

constructor(props) {
    super(props);
    this.state = { };
    this.getColorValue = this.getColorValue.bind(this);
}

3- Using arrow function:

onClick = {e => that.getColorValue(e) }

4- Using class property syntax:

onclick = {this.getColorValue}

getColorValue = (e) => {
   console.log('e', this.props)
}

When you create a new function, like this:

function() {
    this.props.action(name);
});

This is bind to the new function context. Every function has a different this in javascript. You can solve this in a few ways:

Use arrow functions if you have them (they won't rebind this)

() => {
    this.props.action(name);
});

Rebind this with bind

function() {
    this.props.action(name);
}.bind(this));

Save this in a variable

var that = this;
function() {
    that.props.action(name);
});

Choose the first if you have a transpiler, like babel! Otherwise it's your call.

本文标签: javascriptReact thisprops is nullStack Overflow