繁体   English   中英

反应重新渲染组件两次?

[英]React re-rendering components twice?

所以我目前有一个有效的“待办事项”列表实现,它使用 Rails 作为后端 API 和 React 作为前端(连同 axios 发出请求)。 我熟悉 Rails,但 React 对我来说还是个新手。

目前我有 4 个组件,但我关心的 2 个是ListListItem

List.js

import React, { Component } from 'react';
import axios from 'axios';
import ListItem from './ListItem';


class List extends Component { 
    constructor(props){
        super(props)
        this.state = {
            listItems: [],
            newItem: ''
        }
    }

    componentDidMount() {
        axios.get(`/api/v1/lists/${this.props.list.id}/list_items.json`)
        .then(response => {
            this.setState({
                listItems: response.data
            })
        })
        .catch(error => console.log(error))
    }

    addNewListItem = (list_id, content) => {
        axios.post(`/api/v1/lists/${list_id}/list_items`, {
            content: content
          })
        .then(response => {
            const listItems = [ ...this.state.listItems, response.data ]
            this.setState({
                listItems: listItems,
                newItem: ''
            })

        })
        .catch(error => {
            console.log(error)
        })
    }

    removeListItem = (listItem_id) => {
        axios.delete(`/api/v1/list_items/${listItem_id}`)
        .then(response => {
            const listItems = this.state.listItems.filter(
                listItem => listItem.id !== listItem_id
            )
            this.setState({listItems})

        })
        .catch(error => {
            console.log(error)
        })
    }

    handleChange = (e) => {
        this.setState({ newItem: e.target.value });
      }

    render() {
        return (
            <div  key={this.props.list.id}>
            <div className="card">
                <div className="card-body">
                    <h4 className="card-title">{this.props.list.title}</h4>
                    <p className="card-text">{this.props.list.description}</p>
                </div>
                <ul className="list-group list-group-flush">
                    {this.state.listItems.map( listItem => {
                        return <li className="list-group-item" key={listItem.id}><ListItem listItem={listItem} removeListItem={this.removeListItem}/></li>
                    })}
                </ul>
            </div>
                <form>
                    <div className="form-group">
                        <input className="form-control" placeholder="...." value={this.state.newItem} onChange={this.handleChange}/>
                    </div>
                        <button className="btn btn-primary btn-sm mx-1" onClick={() => this.addNewListItem(this.props.list.id, this.state.newItem)}>Add Item</button>
                        <button className="btn btn-info btn-sm mx-1" onClick={() => this.props.onUpdateList(this.props.list.id)}>Update</button>
                        <button className="btn btn-danger btn-sm mx-1" onClick={() => this.props.onRemoveList(this.props.list.id)}>Erase</button>
                </form>
            </div>

        )
    }
}

export default List;

ListItem.js

import React, { Component } from 'react';

const ListItem = (props) =>
    <div className="list-item" >
        {props.listItem.content}
        <button className="float-right btn btn-outline-danger btn-sm" onClick={() => props.removeListItem(props.listItem.id)}>Delete</button>
    </div>

export default ListItem;

ListContainer环绕List但这不是我面临的问题。 似乎当我将一个项目添加到我的列表时,它会导致整个页面的刷新(我可以看到样式 go 离开一秒钟)。 我试图拍摄一个示例视频,但不幸的是视频没有显示它,因为它发生得太快了。

我可以说屏幕正在刷新,因为当我观看控制台并“保留日志”时,我看到了这个:

VM412:1 XHR 完成加载:POST“ http://localhost:3000/api/v1/lists/8/list_items ”。

然后

导航到http://localhost:3000/

所以似乎在我发布到我的 API (并更新状态)之后,我感觉正在发生的事情是它正在重新渲染addNewListItemcomponentDidMount 也许我误用了componentDidMount ,但在组件安装时拉入“最新”项目是最有意义的。

奇怪的是它被重新调用了? componentDidMount不应该只被调用一次吗? (我可以在控制台中告诉它在AddNewListItem基于控制台日志运行后再次被调用。或者它工作正常,这只是本地运行的一些奇怪的浏览器故障?

当您在 forms 中放置按钮并且未指定类型时,它们将默认为submit ,导致您在尝试调用form操作时重新加载您的页面。 养成始终指定按钮类型的习惯 - <button type="button">

对于实际提交表单的按钮,使用<form onSubmit={handleSubmit}>设置submit和处理事件的类型,并记住在那里调用event.preventDefault()以停止页面重新加载。 您不应该使用onClick处理提交按钮,这是不好的做法,因为它不可访问(返回键不会提交表单)。 但是onClick对于非提交操作很好。

您还应该将ListItem包装在备忘录中,因为目前每个项目都在重新协调,即使只有一个项目发生了变化 - export default React.memo(ListItem) ,它的功能等效于React.PureComponent

暂无
暂无

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

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