开发者问题收集

未捕获的类型错误:无法设置 null 的属性“onclick”,无法打开我的弹出窗口

2018-08-20
1283

我正在使用 react,我试图简单地显示我的弹出窗口 onclick 但我有这个错误

Uncaught TypeError: Cannot set property 'onclick' of null
    at eval (index.js:33)
    at Object../src/index.js (main.js:680)
    at __webpack_require__ (main.js:20)
    at eval (index.js:9)
    at Object../examples/src/index.js (main.js:97)
    at __webpack_require__ (main.js:20)
    at eval (webpack:///multi_(:3001/webpack)-dev-server/client?:2:18)
    at Object.0 (main.js:702)
    at __webpack_require__ (main.js:20)
    at main.js:84

这是我的完整 index.js

import React from 'react';
import './style.scss';
import ReactDOM from "react-dom";

const modal = document.getElementById('myModal');

const btn = document.getElementById("myBtn");

const span = document.getElementsByClassName("close")[0];

btn.onclick = function() {
    modal.style.display = "block";
};

span.onclick = function() {
    modal.style.display = "none";
};

window.onclick = function(event) {
    if (event.target === modal) {
        modal.style.display = "none";
    }
};

class MyComponent 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 (
            <div style={{margin:'auto', float:'none'}}>

                <button id="myBtn">Open Modal</button>
                <div id="myModal" className="modal">
                    <div className="modal-content">
                        <span className="close">&times;</span>
                        <p>Some text in the Modal..</p>
                    </div>

                </div>

                <table cellSpacing="0" cellPadding="0" style={{margin:'0 auto',marginBottom:'2rem'}}>
                    <thead>
                    <tr>
                        <td>
                    <span
                        style={{
                            height: '100px',
                            width: '100px',
                            backgroundColor: 'darkgrey',
                            borderRadius: '50%',
                            display: 'inline-block'
                        }}/>
                        </td>
                        <td style={{color:'#2c4e88'}}>
                            <h1><p>swedavia</p></h1>
                            <h2><p>swedish airports</p></h2>
                        </td>
                    </tr>
                    </thead>
                </table>


                <form onSubmit={this.handleSubmit}>
                    <div style={{color:'darkgrey',padding: '16px'}}>
                        <label htmlFor="uname">Username</label>
                        <input type="text" value={this.state.value} onChange={this.handleChange} />
                        <label htmlFor="psw">Password</label>
                        <input type="password" name="psw" required/>
                        <div style={{marginTop:'2rem'}}>
                            <button type="submit">ОТПРАВИТЬ</button>
                            <span style={{float: 'right',paddingTop: '16px'}}><a href="#">Forgot password?</a></span>
                        </div>
                    </div>
                </form>

            </div>
        );
    }
}

export default MyComponent;

ReactDOM.render(
    <MyComponent />,
    document.getElementById('root')
);

我不明白为什么我会有这个错误,请帮帮我!

也许是因为我使用的是简单的 javascript...

抱歉,如果这是一个愚蠢的问题...但有时我真的不明白简单的事情。

2个回答

这是因为,您试图在元素实际创建之前将其附加到点击处理程序。这就是为什么它会抛出错误:

Uncaught TypeError: Cannot set property 'onclick' of null

使用 componentDidMount 生命周期方法来确保在附加点击处理程序时将创建元素。

像这样:

componentDidMount() {
    const modal = document.getElementById('myModal');
    const btn = document.getElementById("myBtn");
    const span = document.getElementsByClassName("close")[0];

    btn.onclick = function() {
        modal.style.display = "block";
    };

    span.onclick = function() {
        modal.style.display = "none";
    };

    window.onclick = function(event) {
        if (event.target === modal) {
            modal.style.display = "none";
        }
    };
}

建议:

直接访问 dom 元素不是一种好方法,更好的方法是使用状态变量并根据该变量应用样式。

像这样:

constructor(){
    super();
    this.state = {
        openModal: false
    }
    this.handleOpenModel = this.handleOpenModel.bind(this);
    this.handlModelClose = this.handlModelClose.bind(this);
}


handleOpenModel() {
    this.setState({
        openModal: true,
    })
}

handlModelClose() {
    this.setState({
        openModal: false,
    })
}

<button id="myBtn" onClick={this.handleOpenModel}>Open Modal</button>

<div
    id="myModal"
    className="modal"
    style={{ display: this.state.openModal ? 'block' : 'none' }}
>
    <div className="modal-content">
        <span className="close" onClick={this.handlModelClose}>&times;</span>
        <p>Some text in the Modal..</p>
    </div>
</div>
Mayank Shukla
2018-08-20

您不能在类之前编写代码来查找元素!

例如:( 完整示例

import React, { Component } from 'react';
import PropTypes from 'prop-types';

class Clicker extends Component {

    constructor(props) {
        super();

        this.state = {
            count: props.count
        };

        this.incrementCount = this.incrementCount.bind(this);
        this.decrementCount = this.decrementCount.bind(this);
        this.resetCount = this.resetCount.bind(this);
    }

    incrementCount() {
        this.setState((prevState) => ({ count: prevState.count + 1 }));
    }

    decrementCount() {
        this.setState((prevState) => ({ count: prevState.count - 1 }));
    }

    resetCount() {
        this.setState(() => ({ count: 0 }));
    }

    render() {
        return (
            <div className="container">
                <div className="clicker border border-secondary rounded">
                    <div className="clicker-display d-flex align-items-center bg-light text-secondary">                        
                        <div className="mx-auto display-1">{this.state.count}</div>
                    </div>
                    <div className="clicker-button-panel d-flex flex-row">
                        <button className="btn btn-success w-100" onClick={this.incrementCount}>
                            <i className="fa fa-plus fa-2x"></i>
                        </button>
                        <button className="btn btn-warning w-100" onClick={this.resetCount}>
                            <i className="fa fa-refresh fa-2x"></i>
                        </button>
                        <button className="btn btn-danger w-100" onClick={this.decrementCount}>
                            <i className="fa fa-minus fa-2x"></i>
                        </button>
                    </div>
                </div>
            </div>
        );
    }
}

Clicker.defaultProps = {
    count: 0
};

Clicker.propTypes = {
    count: PropTypes.number
};

export default Clicker;
morteza ataiy
2018-08-20