简体   繁体   English

React&Typescript:无法读取未定义的属性“ 0”

[英]React & Typescript: Cannot read property '0' of undefined

I recently moved from .jsx to .tsx, and I'm having issues (before moving to typescript, was all working well). 我最近从.jsx移到.tsx,但遇到了一些问题(在移入打字稿之前,一切正常。) The first error is at line: " <Modal show={this.state.isOpen[key]} onClose={this.handleToggleModal.bind(__this,key)}> ". 第一个错误在行上:“ <Modal show={this.state.isOpen[key]} onClose={this.handleToggleModal.bind(__this,key)}> ”。 I suspect there's something related to typescript, but I don't know what. 我怀疑有与打字稿有关的东西,但我不知道是什么。 Anybody can help me? 有人可以帮助我吗?

// TaskCard.tsx

//Dependencies
import * as React from 'react';

//Copmponents
import Modal, {ModalProps} from './Modal';
import Input from './Input';
import {IBoard} from './Board';
import PostComment from './PostComment';

export interface IComments{
    body: string,
    from: string,
    date: string,
    hour: string
}

export interface ITask{
    board: string,
    duedate: string,
    tag: string,
    tagClass: string,
    tagText: string,
    body: string,
    risk: string,
    responsable: string
    comments: IComments[]
}

export interface TaskProps{
    tasks: ITask[]
    boards: IBoard[]
}

export interface TaskState{
    isOpen: {}
}

class TaskCard extends React.Component<TaskProps, TaskState>{
    constructor(props) {
        super(props);

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

    handleToggleModal(key) {
        this.state.isOpen[key] = !this.state.isOpen[key];
        this.setState(this.state.isOpen);
    }

    render(){
        const { tasks, boards } = this.props;
        let __this = this;

        return(
            tasks && tasks.map(
                (tasks, key) =>
                <div key={key} className="v-margin no-margin-top card-contour medium" onClick={this.handleToggleModal.bind(__this,key)}>
                    <div className="row middle-xs caption">
                        <div className="col-xs-6 no-padding">
                            <div className="row middle-xs">
                                <img className="img_icn no-padding-left" src="./assets/img/icn_calendar.svg" alt=""/>
                                <p className="txt-tertiary-color">{tasks.duedate}</p>
                            </div>
                        </div>
                        <div className="col-xs-6 no-padding">
                            <div className="row end-xs middle-xs">
                                <div className={tasks.tagClass + " tag tag_box center-align"}>
                                    <p>{tasks.tag}</p>
                                    <span className="tag_hint">{tasks.tagText}</span>
                                </div>
                            </div>
                        </div>
                    </div>
                    <div className="row middle-row v-padding">
                        <p>{tasks.body}</p>
                    </div>
                    <div className="row middle-xs caption">
                        <div className="col-xs-9 no-padding">
                            <div className="row middle-xs">
                                <img className="img_icn no-padding-left" src="./assets/img/icn_target.svg" alt=""/>
                                <p className="txt-tertiary-color">Riesgos: {tasks.risk}%</p>
                            </div>
                        </div>
                        <div className="col-xs-3 no-padding">
                            <div className="row middle-xs end-xs">
                                <img className="img_icn no-padding-left" src="./assets/img/icn_comments.svg" alt=""/>
                                <p className="txt-tertiary-color">{tasks.comments.length}</p>
                            </div>
                        </div>
                    </div>
                    <Modal show={this.state.isOpen[key]} onClose={this.handleToggleModal.bind(__this,key)}>
                        <div className="modal_container">
                            <section className="modal_section">
                                <div className="row middle-xs no-margin-left no-margin-right modal_section_title">
                                    <object width="20px" height="20px" data="./assets/img/icn_objetive-blue.svg"></object>
                                    <div className="col-xs start-xs">
                                        <h4 className="semi-bold">Objetivo</h4>
                                    </div>
                                </div>
                                <div className="col-xs-12 modal_section_content">
                                    <p>{tasks.body}</p>
                                </div>
                            </section>
                            <section className="modal_section">
                                <div className="row middle-xs no-margin-left no-margin-right modal_section_title">
                                    <object width="20px" height="20px" data="./assets/img/icn_target-blue.svg"></object>
                                    <div className="col-xs start-xs">
                                        <h4 className="semi-bold">Target</h4>
                                    </div>
                                </div>
                                <div className="col-xs-12 modal_section_content">
                                    <p>Riesgos / Problemas = {tasks.risk}%</p>
                                    <div className="table v-margin">
                                        <div className="row middle-xs">
                                            <div className="col-xs">
                                                <p className="table_head">Fecha de vencimiento</p>
                                                <p className="table_body">{tasks.duedate}</p>
                                            </div>
                                            <div className="col-xs">
                                                <p className="table_head">Tipo de objetivo</p>
                                                <p className="table_body">{tasks.tagText}</p>
                                            </div>
                                            <div className="col-xs">
                                                <p className="table_head">Responsable</p>
                                                <p className="table_body">{tasks.responsable}</p>
                                            </div>
                                            <div className="col-xs-12 v-margin no-margin-bottom">
                                                <p className="table_head">Estado de objetivo</p>
                                                <div className="row middle-xs">
                                                    {
                                                        boards && boards.map(
                                                        (boards, board) =>
                                                        <div key={board} className="col-xs-3">
                                                            <Input name="state" type="radio" classNameCustom="input_radio"
                                                            checked={boards.id == tasks.board} value={boards.id} id={boards.id}/>
                                                            <label htmlFor={boards.id}>{boards.name}</label>
                                                        </div>
                                                        )
                                                    }
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>
                            </section>
                            <section className="modal_section">
                                <div className="row middle-xs no-margin-left no-margin-right modal_section_title">
                                    <object width="20px" height="20px" data="./assets/img/icn_activity-blue.svg"></object>
                                    <div className="col-xs start-xs">
                                        <h4 className="semi-bold">Actividad</h4>
                                    </div>
                                </div>
                                <div className="col-xs-12 modal_section_content">
                                    {
                                        tasks.comments.length!=0 ?(
                                            tasks.comments.map((comments, i) => {
                                                return(
                                                    <div key={i} className="comment">
                                                        <div className="comment_box">
                                                            <p>{comments.body}</p>
                                                        </div>
                                                        <div className="comment_data row no-margin middle-xs">
                                                            <div className="col-xs start-xs">
                                                                <p>{comments.from}</p>
                                                            </div>
                                                            <div className="col-xs end-xs">
                                                                <p>{comments.date} a las {comments.hour} hs.</p>
                                                            </div>
                                                        </div>
                                                    </div>
                                                )
                                            })
                                        ):null                                
                                    }
                                </div>
                            </section>
                        </div>
                        <PostComment />
                    </Modal>
                </div>
            )
        )
    }
}

export default TaskCard;

And here is the Modal component 这是模态组件

//Modal.tsx file
//Dependencies
import * as React from 'react';

export interface ModalProps{
    onClose: any,
    show: boolean,
    children: any
}

export default class Modal extends React.Component<ModalProps>{
    handleStopPropagation = (e) =>{
        e.stopPropagation();
    }

    render(){
        const {onClose, show, children} = this.props;

        // Render nothing if the "show" prop is false
        if(!this.props.show) {
            return null;
        }

        return (
            <div className="modal_bkg" onClick={this.handleStopPropagation}>
                <div className="modal_bkg_container row middle-xs center-xs">
                    <div className="modal card">
                        <div className="right-align modal_close">
                            <button className="btn btn_close" onClick={this.props.onClose}>x</button>
                        </div>
                        {this.props.children}
                    </div>
                </div>
            </div>
        );
    }
}

I'm unable to run the code at the moment, but as far as I can see the TaskCard.render function is using Array.map function, which is executing a callback function for every task item. 目前,我无法运行代码,但据我TaskCard.render函数正在使用Array.map函数,该函数正在为每个任务项目执行回调函数。

And there is a problem, because in the callback this is not the this you think it is :). 这是一个问题,因为在回调中this不是您认为的this :)。 According to documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/map you can use map overload that accepts this . 根据文档: https : //developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Array/map,您可以使用接受this地图重载。

I believe that if you do 我相信,如果你这样做

return(tasks && tasks.map(
            (tasks, key) => <div>put your component markup here</div>,
            this)
      );

inside TaskCard.render function you should see the error no more. TaskCard.render函数中,您应该不再看到该错误。

A friend helped me with this and now it's working. 一个朋友帮了我这个忙,现在可以了。 The first problem was the state "isOpen" at start always is undefined so, that's why runtime was throwing error "Cannot read property '0' of undefined". 第一个问题是启动时始终未定义状态“ isOpen”,因此这就是运行时引发错误“无法读取未定义的属性'0'”的原因。 So now, "isOpen" is and empty object and the final constructor looks like this: 因此,现在,“ isOpen”是并且为空对象,最终的构造函数如下所示:

constructor(props) {
    super(props);

    this.state = { 
        isOpen: {}
    };
}

After this, another error was "boards.map is not a function" and that was because I was passing the array "boards" as object. 此后,另一个错误是“ boards.map不是函数”,这是因为我将数组“ boards”作为对象传递了。 Changing for "board" was enought. 换“木板”就足够了。 So the final code was: 所以最终的代码是:

boards && boards.map(
    (board, key) =>
    <div key={key} className="col-xs-3">
       <Input name="state" type="radio" classNameCustom="input_radio"
       checked={board.id == task.board} value={board.id} id={board.id}/>
       <label htmlFor={board.id}>{board.name}</label>
    </div>
)

Anyway, thanks for trying to help me. 无论如何,感谢您尝试帮助我。 Regards! 问候!

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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