反应:基于子组件重新渲染父组件

时间:2018-10-03 15:35:48

标签: javascript reactjs

我有一个名为Cart的父组件和另一个名为Items的组件。 基本上,我是从Node.js获取对象数组并将其另存为Cart组件中的状态。

我的购物车组件:

class Cart extends React.Component {
    constructor(props){
        super(props)

        this.state={
            cartData:null,
        }

    }

    componentWillUnmount(){
        _isMounted = false

    }

    componentDidMount() {
        _isMounted = true
        this.callApi()
        .then(res => {if(_isMounted) this.setState({cartData: res.express})})
        .catch(err => console.log(err));
      }

    callApi = async () => {
        const response = await fetch('/myCart');
        const body = await response.json();
        if (response.status !== 200) throw Error(body.message);

        return body;

    };

    mapOutItems(){
        return this.state.cartData.map((item,index) => (
            <Item
                key={index}
                desc={item.desc}
                amount={item.amount}
                total={item.total}
                delete={this.handleDelete(item.desc)}
            />
        ))
    }
    handleDelete(desc){
        axios({method: "post", url: "/remove", data:{name: desc}})

        axios("/myCart").then(function (response){
            this.setState({cartData : response.data.express})
        })
        .catch(function (error){
            console.log(error)
        });
    }

    render(){
        return(
            <div>
                <div className="container">
                    {this.mapOutItems()}
                </div>
            </div>
        )
    }
}

export default Cart;

项目组件

class Item extends React.Component{
    handleClick(e){
        e.preventDefault()
        axios({method: "post", url: "/remove", data:{name: this.props.desc}})
    }
    render(){
        return(
            <div>
                <div className="row">
                    <div className="col">
                        {this.props.desc}
                    </div>
                    <div className="col">
                        {this.props.amount}
                    </div>
                    <div className="col">
                        {this.props.total}
                    </div>
                    <button className="btn btn-sm btn-danger" onClick=onClick={this.props.delete}>
                        Delete
                    </button>
                </div>
            </div>
        )
    }
}

export default Item;

逻辑:我的Cart组件将从Node.js的端点获取数据。它是一个对象数组,Cart组件使用它来填充item组件。 item组件具有一个删除按钮,一旦触发,该按钮将发送要删除的项目的名称,并使用MongoDB的查询删除该项目。 但是,后端表明已成功删除它,但是父级Cart组件仍呈现已删除的项目。我想找到一种删除物品后触发购物车重新渲染的方法。

编辑:

来自url的简单数据是一个像这样的对象数组:

[{ desc: 'Market', total: 4000, amount: 1 }
{ desc: 'Data', total: 17000, amount: 1 }]

handleDelete()中的响应是被称为axios的响应,格式如下:

{data: {…}, status: 200, statusText: "OK", headers: {…}, config: {…}, …}
config: {adapter: ƒ, transformRequest: {…}, transformResponse: {…}, timeout: 0, xsrfCookieName: "XSRF-TOKEN", …}
data: {express: Array(1)}
headers: {date: "Wed, 03 Oct 2018 18:30:02 GMT", etag: "W/"37-QxQ/lxfNH/fWEmtfXYAG1YLiA/E"", x-powered-by: "Express", content-length: "55", vary: "Accept-Encoding", …}
request: XMLHttpRequest {onreadystatechange: ƒ, readyState: 4, timeout: 0, withCredentials: false, upload: XMLHttpRequestUpload, …}
status: 200
statusText: "OK"
__proto__: Object

response.data,我得到express: Array(1),所以从response.data.express,我实际上是在获取数据数组

@ Code-Apprentice的编辑后。现在的问题是,在完成第一个删除调用之后,第二个被调用的axios没有调用get invoke。我试图打印出我从第二个轴测仪得到的结果,并且它与第一个渲染的数据相同。

3 个答案:

答案 0 :(得分:1)

要触发任何组件的重新呈现,可以调用this.setState()。在这种情况下,您需要从cartData中删除已删除的项目,并调用类似this.setState({cartData: updatedData});的名称。 (确保映射到cartData中的testData而非render()上。)

为此,您需要一个回调函数,该回调函数作为prop从Cart传递到Item。例如,将其命名为onDelete()。该功能负责实现上一段中描述的逻辑。您可以通过以下两种方式之一来实现此目的:

  1. 从后端获取数据。这将为您提供数据库中项目的准确列表。

  2. this.state.cardData中删除已删除的项目。这样比较快,因为您不必发出网络请求,但是可能会删除错误的项目,从而使组件的状态与后端数据库中的数据不同。

附录:

在当前版本中,您尝试使用以下代码行传递回调:

delete={this.handleDelete(item.desc)}

问题在于,当您在购物车数据中的每个商品上进行映射时,这会立即this.handleDelete()调用。因此,每个项目均被删除。相反,您需要创建一个函数,该函数将在单击按钮时执行:

delete={() => this.handleDelete(item.desc)}

答案 1 :(得分:0)

因此,基本上,删除商品后,您需要更新购物车组件中的状态。为此,您可以再次获取数据或从购物车状态中仅删除该项目。在以下代码段中,handleDelete将从cartData中拼接该项并将其设置为state,该状态将触发组件渲染。

<Item
    key={index}
    desc={item.desc}
    amount={item.amount}
    total={item.total}
    onDelete={this.handleDelete}
/>

handleClick(e){
    e.preventDefault()
    axios({method: "post", url: "/remove", data:{name: this.props.desc}}).then(() => {this.props.handleDelete(this.props.desc)})
}

答案 2 :(得分:0)

您应该在父组件中创建一个带有项ID的函数,该函数将负责发出删除请求,并在响应返回后从数组和setState中删除父项的已删除项。 将此函数发送到父渲染方法上的每个项目。 在子组件中,当用户单击删除按钮时,将从父组件调用传递的函数,并将ID传递给该函数。