2017-08-31 3 views
3

Ich habe die folgende Schaltfläche "Kaufen" für einen Einkaufswagen.Löschen bestimmter Redux-Status vor dem Rendern der Komponente

Ich habe auch eine Komponente namens Tooltip, die sich selbst für Fehler/Erfolg Nachrichten angezeigt wird. Es verwendet die Breite der Schaltfläche, um den Mittelpunkt zu bestimmen. Daher benutze ich ein `Ref, da ich auf die physikalische Größe innerhalb des DOM zugreifen muss. Ich habe gelesen, dass es eine schlechte Nachricht ist, ein ref-Attribut zu verwenden, aber ich bin mir nicht sicher, wie ich sonst die Positionierung einer untergeordneten Komponente, die auf dem physischen DOM basiert, durchführen könnte. Aber das ist eine andere Frage ...;)

Ich beharre den Status der App in localStorage. Wie hier zu sehen: https://egghead.io/lessons/javascript-redux-persisting-the-state-to-the-local-storage

Das Problem, das ich renne ist, dass ich die Eigenschaft success des Staates vor dem Rendern löschen muss. Andernfalls, wenn ich eine Erfolgsmeldung in dem Zustand habe, wird auf dem anfänglichen render() Tooltip versuchen, auch zu rendern. Dies ist nicht möglich, da die Schaltfläche, auf die sie angewiesen ist, noch nicht im DOM enthalten ist.

Ich dachte, dass das Löschen des Erfolgszustands über Redux-Aktion in componentWillMount würde den Erfolgszustand aufräumen und damit das Problem klären, aber es scheint, dass die render() -Methode nicht erkennt, dass der Status geändert wurde und wird Zeige immer noch den alten Wert in console.log().

My Work-around ist zu überprüfen, ob die Taste, sowie die Meldung Erfolg besteht: showSuccessTooltip && this.addBtn

Warum erkennt das render() nicht die componentWillMount() Zustandsänderung? Hier

ist die ProductBuyBtn.js Klasse:

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 { 
 

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

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

 
\t render() { 
 

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

 
\t \t console.log(this.props.success) 
 

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

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

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

 
export default connect(mapStateToProps, mapDispatchToProps)(ProductBuyBtn)

Antwort

2

Nun, so scheint es, ein bekanntes Problem zu sein, das einfach in zu erhalten (schwerer zu bekommen aus, vor allem in einem schönen/nicht-hacky Weise. Sehen Sie this super-long thread).

Das Problem ist, dass eine Aktion in componentWillMount Dispatching, dass (schließlich) ändert die Requisiten auf eine Komponente geht in garantiert nicht, dass die Handlung vor dem gefunden hat zuerst machen.

Also im Grunde ist die render() nicht für geschickt Aktion warten zu übernehmen, es (mit den alten Requisiten) einmal macht, dann nimmt die Aktion Wirkung und ändert die Requisiten und dann die Komponente mit der Wieder rendert neue Requisiten.

So müssen Sie entweder tun, was Sie bereits tun, oder verwenden Sie den internen Zustand der Komponenten, um zu verfolgen, ob es das erste Rendern ist oder nicht, etwas wie this comment. Es gibt mehr Vorschläge, aber ich kann sie nicht alle aufzählen.

+1

Vielen Dank. Ich war mir nicht sicher, ob es eine "Best Practice" gab oder nicht. Sie haben meine ersten Gedanken dazu gemacht, dass die Komponente rendert, bevor der Zustand tatsächlich geändert wird. Es ist aber seltsam, weil ich eine console.log im Reducer gemacht habe, um zu sehen, wann es geschossen hat, und es schien vor dem Rendern zu geschehen. Ich schätze, es täuscht. – Gurnzbot

+1

Kein Problem! Ich sollte sagen, dass ich kein Redux-Experte bin, also empfehle ich zumindest einen Blick auf den Thread, den ich verlinkt habe, nur um sicher zu sein, dass ich den Inhalt nicht falsch darstellte.Aber ich erinnere mich, dass ich vorher in ähnliche Situationen gerannt bin (und ich erinnere mich nicht, dass sie jemals eine saubere Lösung bekommen haben). Ich wäre nicht allzu überrascht, wenn sich herausstellt, dass das Problem vermieden werden kann, wenn die Anwendung anders strukturiert ist, aber ich weiß nicht wie (und soweit ich das beurteilen konnte, auch die Leute in der Thread, oder zumindest gab es keinen Konsens darüber, wie.) – jonahe

+1

Ich ging schnell über den Thread, den Sie gepostet (Danke!). Es scheint, dass jeder wirklich Workarounds macht. Vielleicht sind sie ja gar keine Workarounds, da es genau so ist, wie es gemacht wird;) Dies ist eine dieser Zeiten, ich bin froh, dass jeder dieses Thema hat und ich bin kein lahmer Entwickler. – Gurnzbot

Verwandte Themen