在呈现组件

时间:2017-08-31 20:01:57

标签: javascript reactjs redux react-lifecycle

我有以下"购买"购物车按钮。

我还有一个名为Tooltip的组件,它会显示错误/成功消息。它使用按钮的宽度来确定它的中心点。因此,我使用`ref,因为我需要在DOM中访问它的物理大小。我已经读过使用ref属性的坏消息,但是我不确定如何定位基于物理DOM的子组件。但那是另一个问题......;)

我在localStorage中坚持应用程序的状态。如下所示: https://egghead.io/lessons/javascript-redux-persisting-the-state-to-the-local-storage

我遇到的问题是我必须在渲染之前清除状态success属性。否则,如果我在状态中有成功消息,则在初始render()上,Tooltip也将尝试渲染。这是不可能的,因为它依赖的按钮还没有在DOM中。

我认为通过componentWillMount中的Redux操作清除成功状态会清除成功状态,从而解决问题,但似乎render()方法无法识别状态已更改,仍将在console.log()中显示旧值。

我的解决方法是检查按钮是否存在以及成功消息:showSuccessTooltip && this.addBtn

为什么render()无法识别componentWillMount()状态更改?

这是ProductBuyBtn.js类:



import React, { Component } from 'react';
import { connect } from 'react-redux'

// Components
import Tooltip from './../utils/Tooltip'

// CSS
import './../../css/button.css'

// State
import { addToCart, clearSuccess } from './../../store/actions/cart'

class ProductBuyBtn extends Component {

	componentWillMount(){
		this.props.clearSuccess()
	}

	addToCart(){
		this.props.addToCart(process.env.REACT_APP_SITE_KEY, this.props.product.id, this.props.quantity)
	}

	render() {

		let showErrorTooltip = this.props.error !== undefined
		let showSuccessTooltip = this.props.success !== undefined

		console.log(this.props.success)

		return (
			<div className="btn_container">
				<button className="btn buy_btn" ref={(addBtn) => this.addBtn = addBtn } onClick={() => this.addToCart()}>Add</button>
				{showErrorTooltip && this.addBtn &&
					<Tooltip parent={this.addBtn} type={'dialog--error'} messageObjects={this.props.error} />
				}
				{showSuccessTooltip && this.addBtn &&
					<Tooltip parent={this.addBtn} type={'dialog--success'} messageObjects={{ success: this.props.success }} />
				}
			</div>
		);
	}
}

function mapStateToProps(state){
	return {
		inProcess: state.cart.inProcess,
		error: state.cart.error,
		success: state.cart.success
	}
}

const mapDispatchToProps = (dispatch) => {
	return {
		addToCart: (siteKey, product_id, quantity) => dispatch(addToCart(siteKey, product_id, quantity)),
		clearSuccess: () => dispatch(clearSuccess())
	}
}

export default connect(mapStateToProps, mapDispatchToProps)(ProductBuyBtn)
&#13;
&#13;
&#13;

1 个答案:

答案 0 :(得分:3)

好吧,这似乎是一个容易进入的已知问题(更难以摆脱,特别是以漂亮/非黑客的方式。请参阅this super-long thread)。

问题是,在componentWillMount中调度(最终)更改进入组件的道具的操作并不能保证在第一次渲染之前发生了操作。< / p>

所以基本上render()没有等待你的调度动作生效,它渲染一次(使用旧道具),然后动作生效并更改道具和然后< / em>组件使用新道具重新渲染。

所以你要么必须做你已经做的事情,要么使用组件内部状态来跟踪它是否是第一个渲染,如this comment。概述了更多建议,但我无法全部列出。