【问题标题】:React map always calls method with data of last elementReact map 总是使用最后一个元素的数据调用方法
【发布时间】:2019-02-15 09:23:14
【问题描述】:

我正在制作一个社交媒体应用程序。我正在遍历所有 cmets 并将其显示在 UI 上。当我点击编辑时,最后一条评论的文本总是显示在输入中。我尝试了许多不同的东西,改变了结构,使用 bind 来绑定上下文,但没有任何帮助。

我正在使用 React Material UI。

代码如下:

render() {

    const { anchorEl } = this.state;
    const open = Boolean(anchorEl);

    return(
        <Panel>
            <form noValidate autoComplete="off" onSubmit={this.onSubmit}>
                <TextField
                    id={`comment${this.state.post_id}`}
                    name="comment"
                    fullWidth
                    placeholder="Comment here"
                    margin="normal"
                    value={this.state.comment}
                    onChange={this.handleChange}
                    InputProps={{
                        endAdornment : <InputAdornment position="end">
                            <IconButton onClick={this.resetTextField}>
                                <CloseIcon/>
                            </IconButton>
                        </InputAdornment>
                    }}
                />
            </form>

            {this.props.comments && this.props.comments.length > 0 &&
            <RenderComments
                comments={this.state.comments}
                open={open}
                anchorEl={this.state.anchorEl}
                handleClick={this.handleClick}
                handleClose={this.handleClose}
                handleDelete={this.handleDelete}
                handleEdit={this.handleEdit}
            />
            }
        </Panel>
    )
}

const RenderComments = (props) => {
    return props.comments.map(comment =>
        <CommentBase
            key={comment.id}
            comment={comment}
            open={props.open}
            anchorEl={props.anchorEl}
            handleClick={props.handleClick}
            handleClose={props.handleClose}
            handleDelete={props.handleDelete}
            handleEdit={props.handleEdit}
        />
    );
};

    const CommentBase = ({comment, open, anchorEl, handleClick, handleClose, handleDelete, handleEdit}) => (
    <CommentBasePanel>
        <CommentText>
            {comment.text}
            <span style={{ float: 'right', fontSize: 10, color: '#A9A9A9' }}>{moment(comment.created_at).fromNow()}</span>
        </CommentText>
        <HelperAction>
            <MoreVertIcon
                id={comment.id}
                aria-owns={open ? `simple-popper${comment.id}` : null}
                aria-haspopup="true"
                variant="contained"
                onClick={handleClick}
            />
            <Popover
                id={`simple-popper${comment.id}`}
                open={open}
                anchorEl={anchorEl}
                onClose={handleClose}
                anchorOrigin={{
                    vertical: 'bottom',
                    horizontal: 'right',
                }}
                transformOrigin={{
                    vertical: 'top',
                    horizontal: 'right',
                }}
            >
                <Typography style={{ padding: 10, cursor: 'pointer' }} onClick={() => handleEdit(comment)}>
                    Edit
                </Typography>
                <Typography style={{ padding: 10, color: red[500], cursor: 'pointer' }} onClick={() => handleDelete(comment.id)}>
                    Delete
                </Typography>
            </Popover>
        </HelperAction>
    </CommentBasePanel>
);

handleEdit = (comment) => {
    this.setState({ comment: comment.text, comment_id: comment.id })
};

无论我编辑什么评论,handleEdit 方法中的控制台登录评论总是记录最后一条评论。编辑第一条评论给出最后一条评论文本,如图所示。

【问题讨论】:

  • 似乎问题出在 Material UI 弹出窗口上,因为加载时不可见,这会导致一些参考问题。从弹出窗口中直接在屏幕上获取编辑和删除文本解决了这个问题。
  • 检查一下 - 在&lt;Popover/&gt; 中渲染&lt;Typography&gt;{comment.id}&lt;/Typography&gt;?它与范围相关

标签: reactjs es6-map


【解决方案1】:

如果您更新您的RenderComments 渲染方法如下,它应该可以解决您的问题:

const RenderComments = (props) => {
    return props.comments.map(comment =>
        <CommentBase
            key={comment.id}
            comment={comment}
            open={props.open}
            anchorEl={props.anchorEl}
            handleClick={ props.handleClick }
            handleClose={ props.handleClose }
            handleDelete={ () => props.handleDelete(comment.id) }
            handleEdit={ () => props.handleEdit(comment) }
        />
    );
};

【讨论】:

  • 谢谢,但它不起作用。再也看不到编辑的浮动了。我认为 cz handleClick 也是道具,而不是像 onClick 这样的合成事件。
  • @ParthChokshi 刚刚更新 - 这对你有用吗?
  • 不。它没有。该 handleEdit 是从 CommentBase 的功能组件内部调用的。虽然这里没什么区别,但应该是 handleEdit = {cmnt => props.handleEdit(cmnt)};
【解决方案2】:

糟糕的弹出框管理

map 将相同的 openanchorEl 道具复制到所有 Popover 实例 - handleClick(你没有显示这个)*在同一个地方打开所有它们**(最后一个打开顶部)。

修复:handleClick 中包含id,保存在状态中并在状态中使用open 属性

FIX2:您可以使用一个&lt;Popover/&gt; 实例,尤其是在不显示与特定评论相关的任何内容时。

PS。我花了更多的时间在 stackblitz 中重新创建这个(猜测丢失的部分)而不是真正的调试(实际上只检查了 &lt;Popover/&gt; 的 html 结构和渲染的 {comment.id})。下次展示更完整的代码或提供最小的工作示例。

【讨论】:

    猜你喜欢
    • 2020-04-22
    • 2017-04-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-19
    • 1970-01-01
    • 2014-11-12
    • 2019-02-08
    相关资源
    最近更新 更多