2017-10-14 18 views
0

Donc, j'ai une fonction qui convertit les images en base64. Cette fonction est asynchrone et convertit 4 images à l'aide de Promise.all(), puis je renvoie l'objet avec les chaînes reçues. Donc, j'exporte la fonction asynchrone. Voici le code:Async/Await in Redux

import IMAC from '../assets/Images/devices/mac_monitor.png'; 
import MACBOOK from '../assets/Images/devices/macbook_pro.png'; 
import IPHONE_8 from '../assets/Images/devices/iphone_8.png'; 
import MSI_LAPTOP from '../assets/Images/devices/msi_laptop.png'; 

function loadImage(img) { 
    return new Promise((resolve, reject) => { 
     toDataURL(img, function (dataUrl) { 
      resolve(dataUrl); 
     }) 
    }); 
} 

function toDataURL(url, callback) { 
    const xhr = new XMLHttpRequest(); 
    xhr.onload = function() { 
     let reader = new FileReader(); 
     reader.onloadend = function() { 
      callback(reader.result); 
     }; 
     reader.readAsDataURL(xhr.response); 
    }; 
    xhr.open('GET', url); 
    xhr.responseType = 'blob'; 
    xhr.send(); 
} 

const IMAC_IMG_BASE64 = loadImage(IMAC); 
const MACBOOK_IMG_BASE64 = loadImage(MACBOOK); 
const MSI_IMG_BASE64 = loadImage(MSI_LAPTOP); 
const PHONE_IMG_BASE64 = loadImage(IPHONE_8); 

export async function loadAllImages() { 
    const result = await Promise.all([IMAC_IMG_BASE64, MACBOOK_IMG_BASE64, MSI_IMG_BASE64, PHONE_IMG_BASE64]); 
    return [ 
     { 
      id: 0, 
      device: "Apple iMac", 
      image: result[0], 
      styles: { 
       carousel_item: { 
        width: "41.6vw", 
        height: "auto", 
        top: "-4.095vw", 
        left: "-0.13vw" 
       }, 
       carousel: { 
        height: "38vw", 
        margin: "50px 0" 
       }, 
       device: { 
        width: "46.5vw", 
        height: "38vw", 
        marginLeft: "-23.25vw" 
       } 
      } 
     }, 
     { 
      id: 1, 
      device: "Apple Macbook Pro", 
      image: result[1], 
      styles: { 
       carousel_item: { 
        width: "37vw", 
        height: "auto", 
        top: "-4.4vw", 
        left: ".6vw" 
       }, 
       carousel: { 
        height: "38vw", 
        margin: "50px 0" 
       }, 
       device: { 
        width: "55vw", 
        height: "30vw", 
        marginLeft: "-27.5vw" 
       } 
      } 
     }, 
     { 
      id: 2, 
      device: "MSI GP72VR 7RFX", 
      image: result[2], 
      styles: { 
       carousel_item: { 
        width: "35vw", 
        height: "auto", 
        top: "-5.8vw", 
        left: ".5vw" 
       }, 
       carousel: { 
        height: "38vw", 
        margin: "50px 0" 
       }, 
       device: { 
        width: "50vw", 
        height: "34vw", 
        marginLeft: "-25vw" 
       } 
      } 
     }, 
     { 
      id: 3, 
      device: "Iphone 8", 
      image: result[3], 
      styles: { 
       carousel_item: { 
        width: "14vw", 
        height: "auto", 
        top: "-8.2vw", 
        left: "0" 
       }, 
       carousel: { 
        height: "38vw", 
        margin: "50px 0" 
       }, 
       device: { 
        width: "17.7vw", 
        height: "34vw", 
        marginLeft: "-8.85vw" 
       } 
      } 
     }, 
    ]; 
} 

Ensuite, j'ai ce créateur d'action, qui est async, où j'ai reçu des données de cette fonction (loadAllImages()), puis j'appelle l'expédition (PS - J'utilise redux- thunk)

export const loadConfigs =() => async dispatch => { 
const data = await loadAllImages(); 
dispatch({type: "LOAD_DATA", payload: data}); 
}; 

aussi, j'ai réducteur, où je retourne la charge utile avec l'objet, a reçu de l'envoi appelé

export default (sliderConfig = null, action) => { 
    const {type, payload} = action; 
    switch(type){ 
     case "LOAD_DATA": 
      return payload; 
    } 

    return sliderConfig; 
} 

A l'intérieur du conteneur principal app.js, j'appelle CA à l'intérieur de la Compo nentDidMount() (Ne regardez pas fetchUser(), il n'a pas d'importance dans ce contexte)

componentDidMount() { 
     this.props.fetchUser(); 
     this.props.loadConfigs(); 
    } 

Et puis je le composant, où je me sers de ces données, qui a reçu de l'AC de manière asynchrone. (Ne regardez pas appDesign(), il n'a pas d'importance dans ce contexte)

import React, {Component, PureComponent} from 'react'; 
import appDesign from '../../../decorators/scroll_resize_decorator'; 
import Slider from './Slider'; 
import {connect} from 'react-redux'; 
import * as actions from '../../../actions'; 

//Hint: Use container for the images in the slider 
//Because errors with movement is appeared 
class BlockFour extends Component { 

    render() { 

     if (this.props.sliderElements) { 
      const {sliderElements, width, config, selectConfig} = this.props; 
      return (
       <div className="blockfive"> 
        <div className="blockfive--inner"> 
         <div className="blockfive__container"> 
          <div className="blockfive__container__header"> 
           <div className="blockfive__container__header__container"> 
            <h1>Application Gallery</h1> 
            <p> 
             Lorem ipsum dolor sit amet, consectetur adipisicing elit. 
             A aliquid blanditiis consequuntur debitis deserunt eaque eligendi 
            </p> 
            <div className="blockfive__header--divider"></div> 
           </div> 
          </div> 
          <div className="blockfive__container__device"> 
           <h2> 
            Choose your device to what screenshots 
           </h2> 
           <ul className="tabs"> 
            { 
              sliderElements.map(item => 
              <li 
               key={item.id} 
               className="tab" 
               > 
               <a href="#" 
                onClick={ 
                 () => selectConfig(item.id) 
                } 
               > 
                {item.device} 
               </a> 
              </li> 
             ) 
            } 
           </ul> 
          </div> 
          <div className="blockfive__container__gallery"> 
           { 
             <Slider 
             width={width} 
             styles={sliderElements[config].styles} 
             device_image={sliderElements[config].image} 
            /> 
           } 
          </div> 
         </div> 
        </div> 
       </div> 
      ); 
     } 

     return null 
    } 
} 

const mapStateToProps = ({sliderElements, config}) => { 
    return { 
     sliderElements, 
     config 
    } 
}; 

export default connect(mapStateToProps, actions)(appDesign(BlockFour)); 

Ainsi, cette syntaxe fonctionne, tout chargement et de travail. Donc, j'ai une question: Quelle est la bonne façon d'extraire les données asynchrones dans AC, puis les passer à réducteur, puis charger à l'intérieur du composant. Je ne veux pas utiliser if instruction dans mon composant.

J'ai lu quelques guides sur async/wait AC et comment les utiliser, mais je ne comprends pas complètement comment l'utiliser dans ma situation. Pourriez-vous s'il vous plaît me donner une brève direction sur la façon de le mettre en œuvre ici. Je vous remercie!

+0

vous faites une requête (récupérer ou n'importe quelle bibliothèque que vous allez utiliser) dans le rappel de cette requête vous avez les données .. puis vous envoyez ces données au réducteur –

+0

C'est à peu près ce que vous faites. Pas de problème du tout. – WilomGfx

+0

@WilomGfx Cela fonctionne, oui, mais j'ai lu quelques guides, où les gens écrivent trois AC, c'est DATA_IS_FETCHING, DATA_IS_FETCHED, et DATA_IS_LOADED. Et je ne comprends pas cela approché, et devrais-je l'utiliser ici – Remzes

Répondre

1

Personnellement, et la plupart des gens suivent ce approach. C'est complètement personnel et ne changera pas grand-chose dans votre application, mais pourrait vous rendre la vie plus facile. De cette façon, votre interface utilisateur et d'autres parties de votre application connectées au magasin peuvent agir en conséquence en fonction de l'état.

comprend Exemples: montrant une icône de chargement ou d'un message lorsque FETCH_SMTH_REQUEST est tiré et vos changements d'état à aller chercher et de montrer une erreur lors FETCH_SMTH_FAILURE et vous obtenez le error dans votre état.