简体   繁体   中英

Cannot use the state variable as function parameter? React

I declare a state variable in the constructor. I set the new State in componentDidMount(), and it successfully set the state. But I cannot use this state variable to render my menu. My goal is to render the menu with the data I got from firebase snapshot.

import React from 'react';
import PropTypes from 'prop-types';
import BScroll from 'better-scroll';
import './index.scss';
import Star from '../star';
import Split from '../split';
import {saveToLocal, loadFromLocal} from '@assets/js/store';

import {Card} from 'antd';
import {Menu, Dropdown, Button, Icon, message} from 'antd';
import {Input} from 'antd';
const {TextArea} = Input;
import {Row, Col} from 'antd';
import {List} from 'antd';
import Popup from "reactjs-popup";

import firebase from '../../firebase'; // <--- add this line

export default class needPage extends React.Component {

constructor(props, ctx) {
    super(props, ctx);
    this.state = {
        tableId: "A04",
        needList: [],
        comList: []
    };
}

componentDidMount() {
    this._initScroll();

    const needsRef = firebase.database().ref('needs').orderByChild('tableId').equalTo(this.state.tableId);
    needsRef.on('value', (snapshot) => {

        let allYourNeeds = snapshot.val();
        //console.log(allYourNeeds);
        //console.log(allYourOrders["foodOrders"]);
        let newstate = [];
        let needLists = allYourNeeds;
        for (let need in needLists) {
            //console.log((Date.now() - needLists[need].time)/ 1000 / 60);
            let diff = Math.round((Date.now() - needLists[need].time) / 1000 / 60);
            newstate.push({content: needLists[need].content, time: diff});
        }
        //console.log(allYourOrders["tableId"]);
        this.setState({needList: newstate});
    });

    const comNeedRef = firebase.database().ref('seller').child('comNeeds');
    comNeedRef.on('value', (snapshot) => {

        let allcomNeeds = snapshot.val();
        this.setState({comList: allcomNeeds});
    });
}

componentDidUpdate() {
    this._initScroll();
}

handleButtonClick(e) {
    message.info('您的需求已发送');
    //console.log(document.getElementById("customNeed").value);
    //console.log(Date.now());
    const itemsRef = firebase.database().ref('needs');
    const item = {
        tableId: "A03",
        content: document.getElementById("customNeed").value,
        time: Date.now()
    }
    itemsRef.push(item);
    document.getElementById("customNeed").value = document.getElementById("customNeed").defaultValue;

}

handleMenuClick(e) {
    message.info('需求也发送!');
    console.log('click', e);
}

recursion(dataSource) {
    console.log(dataSource);
    return (dataSource.map((menu, index) => {
        return (<Menu.Item key={menu.key}>{menu.title}</Menu.Item>)
    }))
}
menu = (<Menu onClick={this.handleMenuClick}>
    {this.recursion(this.state.comList)}
</Menu>);

gridStyle = {
    width: '100%',
    textAlign: 'left'
};

render() {
    return (<div className="seller" ref="seller">
        <div className="newNeed">
            <Row>
                <Col span={12} offset={2}>
                    <h1>新的需求</h1>
                </Col>
            </Row>
            <Row>
                <Col offset={2}>
                    <Dropdown overlay={this.menu}>
                        <Button className="dropdwNeed">常需需求
                            <Icon type="down"/></Button>
                    </Dropdown>
                </Col>
            </Row>
            <Row align="bottom">
                <Col span="span" ={15} offset={2}>
                    <div className="textArea">
                        <TextArea id="customNeed" placeholder="在这里手动输入您的需求" autosize="autosize"/>
                    </div>
                </Col>
                <Col span={3} offset={1}>
                    <Button className="submitButton" type="primary" onClick={this.handleButtonClick}>提交</Button>
                </Col>
            </Row>
        </div>
        <div className="ItemsNeed">
            <Row>
                <Col span={24} offset={2}>
                    <h1>您当下的需求</h1>
                </Col>
            </Row>
            <Row>
                <Col span={5} offset={2}>
                    <p className="title1">需求内容</p>
                </Col>
                <Col span={8} offset={8}>
                    <p className="title2">已需时间(分钟)</p>
                </Col>
            </Row>
            <Col offset={2}>
                <List className="listNeed" size="small" bordered="true" itemLayout="horizontal" dataSource={this.state.needList} renderItem={item => (<List.Item>
                        <List.Item.Meta title={item.content}/>
                        <div>{item.time}</div>

                    </List.Item>)}/>
            </Col>
            <Row>
                <h1 className="shuangji">(双击需求可以加急哦!)</h1>
            </Row>
        </div>
        <div className="tousu-contatiner">

            <Popup trigger={<Button className = "tousu" type = "danger" > 不满意!投诉!</Button>} modal="modal">
                {
                    close => (<div className="modal">
                        <a className="close" onClick={close}>
                            &times;
                        </a>
                        <div className="header">
                            投诉内容
                        </div>
                        <TextArea placeholder="在这里手动输入您的不满,我们会直接发送到店主邮箱" autosize="autosize"/>
                        <div className="actions">
                            <Button className="button" onClick={() => {
                                    console.log('modal closed ')
                                    close()
                                }}>提交投诉</Button>
                        </div>
                    </div>)
                }
            </Popup>
        </div>

    </div>);
}

toggleFavorite() {
    this.setState({
        favorite: !this.state.favorite
    });
    saveToLocal(this.context.seller.id, 'favorite', !this.state.favorite);
}

_initScroll() {
    this.scroll = new BScroll(this.refs.seller, {click: true});

}

}

needPage.contextTypes = {
seller: PropTypes.object
};

The Error I got when compile is the following:

index.jsx:102 Uncaught TypeError: Cannot read property 'comList' of undefined
at new needPage (index.jsx:102)
at createClassProxy.js:98
at instantiate (createClassProxy.js:106)
at new needPage (eval at proxyClass (createClassProxy.js:112), <anonymous>:4:17)
at constructClassInstance (react-dom.development.js:11447)
at updateClassComponent (react-dom.development.js:13144)
at beginWork (react-dom.development.js:13824)
at performUnitOfWork (react-dom.development.js:15863)
at workLoop (react-dom.development.js:15902)
at HTMLUnknownElement.callCallback (react-dom.development.js:100)

This should not be a class field:

menu = (<Menu onClick={this.handleMenuClick}>
    {this.recursion(this.state.comList)}
</Menu>);
  1. This is evaluated only once when the component is constructed. Ie updating the state won't regenerate the menu.
  2. This code is executed at the top of the constructor before this.state exists, which is why you get that error.

Move it inside the render method instead.

I used componentWillMount() to fetch data from firebase and uses

<Menu>...</Menu>

directly to overlay in the render method. Problem solved! Thanks both Felix and Tholle, they were both right

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM