简体   繁体   English

反应重新渲染组件两次?

[英]React re-rendering components twice?

So I have a working "Todo" list implementation currently that's using Rails for a backend API and React for the frontend (Along with axios to make requests).所以我目前有一个有效的“待办事项”列表实现,它使用 Rails 作为后端 API 和 React 作为前端(连同 axios 发出请求)。 Im familiar with Rails but React is still new to me.我熟悉 Rails,但 React 对我来说还是个新手。

Currently I have 4 Components, but the 2 I'm concerned with are List and ListItem .目前我有 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 wraps around List however that's not the issue im facing. ListContainer环绕List但这不是我面临的问题。 It seems that when I add an item to my List, it causes a refresh of the entire page (I can see the styling go away for a second).似乎当我将一个项目添加到我的列表时,它会导致整个页面的刷新(我可以看到样式 go 离开一秒钟)。 I tried to take a sample video but unfortunately the video doesn't show it since it happens so quickly.我试图拍摄一个示例视频,但不幸的是视频没有显示它,因为它发生得太快了。

I can tell the screen is refreshing because when I watch the console and "preserve log" I see this:我可以说屏幕正在刷新,因为当我观看控制台并“保留日志”时,我看到了这个:

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

then然后

Navigated to http://localhost:3000/ ?导航到http://localhost:3000/

So it seems like after I POST to my API (and update the state) what I feel like is happening is that it's re-rendering on the addNewListItem AND on the componentDidMount .所以似乎在我发布到我的 API (并更新状态)之后,我感觉正在发生的事情是它正在重新渲染addNewListItemcomponentDidMount Maybe im mis-using componentDidMount but it made the most sense to pull in the "most updated" items when the component mounts.也许我误用了componentDidMount ,但在组件安装时拉入“最新”项目是最有意义的。

It's odd that it's getting re-called though?奇怪的是它被重新调用了? Shouldn't componentDidMount only get called once? componentDidMount不应该只被调用一次吗? (I can tell in my console it's getting called again after the AddNewListItem runs based on console logs. Or maybe it's working fine and this is just some weird browser glitch from running locally? (我可以在控制台中告诉它在AddNewListItem基于控制台日志运行后再次被调用。或者它工作正常,这只是本地运行的一些奇怪的浏览器故障?

When you place buttons in forms and do not specify a type they will default to submit , causing your page you reload as they try to call the form action.当您在 forms 中放置按钮并且未指定类型时,它们将默认为submit ,导致您在尝试调用form操作时重新加载您的页面。 Make a habit of always specifying the button type - <button type="button"> .养成始终指定按钮类型的习惯 - <button type="button">

For the button which actually submits the form, set the type to submit and handle the event with <form onSubmit={handleSubmit}> and remember to call event.preventDefault() in there to stop the page reloading.对于实际提交表单的按钮,使用<form onSubmit={handleSubmit}>设置submit和处理事件的类型,并记住在那里调用event.preventDefault()以停止页面重新加载。 You should not handle submit buttons with onClick this is bad practice as it isn't accessible (Return key won't submit the form).您不应该使用onClick处理提交按钮,这是不好的做法,因为它不可访问(返回键不会提交表单)。 But onClick is fine for non submitting actions.但是onClick对于非提交操作很好。

You should also wrap your ListItem in memo as currently every item is re-reconciling even though only one item changed - export default React.memo(ListItem) which is the functional equivalent of React.PureComponent .您还应该将ListItem包装在备忘录中,因为目前每个项目都在重新协调,即使只有一个项目发生了变化 - export default React.memo(ListItem) ,它的功能等效于React.PureComponent

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

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