尝试在ComponentDidMount中填充具有异步承诺的道具

时间:2018-06-18 18:35:23

标签: javascript reactjs redux

因此,在我不受控制的PossibleMatches组件中,我从React的工作方式知道,初始渲染阶段将发生空的prop值(如果这些prop值依赖于外部应用程序状态(mapStateToProps)),无论我是否有componentDidMount生命周期方法或构造函数设置。为此,我在componentDidMount中设置了一个promise,这样当我调度prop函数[defaultPieces,arrangePieces]时,我可以让UI渲染一个ActivityIndi​​cator来指示当前正在获取的东西。问题是,当我从promise的成功阶段调用mapStateToProps时,我似乎无法获得mapStateToProps函数来理解状态。这是:

class PossibleMatches extends Component {
    constructor(props){
        super(props);
    }

componentDidMount(props){
    return new Promise((resolve, reject) => {
        let state;
        let {defaultPieces, arrangePieces, isFetching} = this.props;
        let makeClothesAppear = function(){
            defaultPieces();
            arrangePieces();
            isFetching = true;
        }

        resolve(makeClothesAppear());
    }).then(function(state){
        mapStateToProps(state);
        this.props.isFetched = true
        this.props.isFetching = false;
    }).catch((error) => {
        console.log('FetchClothesError: ', error);
    })
}
}

用户界面如何决定要显示的内容:

renderDecision(){

        const {UpperComponents, LowerComponents} = this.props;
        const {currentUpperComponent, currentLowerComponent} = this.state.currentComponent.whichPiece;
        const {LowerComponentEnabled, UpperComponentEnabled} = this.state;

        if (this.props.isFetching){
             return (<div className='activityLoader'>
                        <ActivityIndicator number={3} duration={200} activeColor="#fff" borderWidth={2} borderColor="50%" diameter={20}/>
                     </div>);
        } else if (this.props.isFetched){
                return (<div className = "PossibleMatches_Container">
                        <i className = 'captureOutfit' onClick = {this.snapshotMatch}></i> 
                            {UpperComponents.map((component) => {                               
                                    return (<UpperComponent key={component.createdAt} id={component.id} 
                                               switchComponent={this.switchFocus} 
                                               setCurrentPiece = {this.setNewPiece} 
                                               evaluatePiece={this.isOppositeComponentSuggested}
                                               image={component.image}
                                               toggleToPiece = {(LowerComponentEnabled) => {if (LowerComponentEnabled === false){this.setState({LowerComponentEnabled: true})}else{return;} this.setState({currentLowerComponent: this.props.suggestedBottoms[0]})}} 
                                               isLowerComponentEnabled={LowerComponentEnabled}
                                               ref={this.residingUpperComponent}
                                               className = {this.state.currentComponent.whichPiece.whichType === 'match' ? 'PossibleMatches_Container' : this.state.currentComponent.whichPiece.whichType === 'bottom' ? 'standalonePiece' : 'standalonePiece'}/>)
                                    })
                            }
                            {LowerComponents.map((component) => {
                                    return  (<LowerComponent key={component.createdAt} id={component.id} 
                                               setCurrentPiece = {this.setNewPiece} 
                                               evaluatePiece={this.isOppositeComponentSuggested}
                                               image={component.image}
                                               toggleToPiece={(UpperComponentEnabled) => {if (UpperComponentEnabled === false){this.setState({UpperComponentEnabled: true})}else{return;} this.setState({currentUpperComponent: this.props.suggestedTops[0]})}}                
                                               switchComponent={this.switchFocus}
                                               isUpperComponentEnabled={UpperComponentEnabled}
                                               ref={this.residingLowerComponent}
                                               className = {this.state.currentComponent.whichPiece.whichType === 'match' ? 'PossibleMatches_Container' : this.state.currentComponent.whichPiece.whichType === 'bottom' ? 'standalonePiece' : 'standalonePiece'}/>)                                                  
                                    })
                            }
                        </div>)
        }
    }

    render(){


        return(  

                <div className = 'GorClothingContainer'>
                    {/*<Wardrobe upperComponent={this.state.currentComponent.whichPiece.currentUpperComponent} lowerComponent={this.state.currentComponent.whichPiece.currentLowerComponent} enableCapture={(snapshot) => this.snapshotMatch = snapshot} />*/}
                      {this.renderDecision()}
               </div>
            );
    }

我的PossibleMatches Reducer

import {INITIAL_PIECES, GET_ANCILLARY_PIECES, ORGANIZE_PIECES, SET_CONTEMPLATED_PIECE} from '../actions/types';

const initialState = {
     UpperComponents: [],
     LowerComponents: [],
     contemplated_piece: null,
     extraTops: [],
     extraBottoms: [],
     standaloneTops: [],
     standaloneBottoms: [],
     suggestedTops: [],
     suggestedBottoms: []
}

export default function(state = initialState, action){

    switch(action.type){
        case INITIAL_PIECES:
            return Object.assign({}, state, {contemplated_piece: action.payload.contemplated_piece},
                                            {extraTops: action.payload.extra_tops},
                                            {extraBottoms: action.payload.extra_bottoms},
                                            {standaloneTops: action.payload.standalone_tops},
                                            {standaloneBottoms: action.payload.standalone_bottoms},
                                            {suggestedTops: action.payload.suggested_tops},
                                            {suggestedBottoms: action.payload.suggested_bottoms})
        case GET_ANCILLARY_PIECES:
           return Object.assign({}, state, {extraTops: action.payload.extra_tops},
                                           {extraBottoms: action.payload.extra_bottoms},
                                           {standaloneTops: action.payload.standalone_tops},
                                           {standaloneBottoms: action.payload.standalone_bottoms},
                                           {suggestedTops: action.payload.suggested_tops},
                                           {suggestedBottoms: action.payload.suggested_bottoms})
        case ORGANIZE_PIECES:
               return Object.assign({}, state, {UpperComponents: action.payload.UpperComponents},
                                               {LowerComponents: action.payload.LowerComponents})           
        case SET_CONTEMPLATED_PIECE:
           return Object.assign({}, state, {contemplated_piece: action.payload.contemplated_piece})
        default:
            return state;
    }
}

我的combineReducers细分

import {combineReducers} from 'redux';

const allReducers = combineReducers({
 Playlist: PlaylistReducer,
 eventOptions: eventTicketReducer,
 possibleMatches: PossibleMatchesReducer,
 Intro: combineForms({
        basicUserInfo: BasicUserInfoState,
        GenderInfo: GenderInfoState,
        ContactInfo: ContactInfoState
       }, 'Intro'),
 routing: routerReducer,
 form: formReducer
});

道具价值观

PossibleMatches.defaultProps = {
    isFetching: true,
    isFetched: false
}

我的mapStateToProps功能

function mapStateToProps(state){

            return {UpperComponents: state.possibleMatches.UpperComponents,
                    LowerComponents: state.possibleMatches.LowerComponents,
                    contemplatedPiece: state.possibleMatches.contemplated_piece,
                    extraTops: state.possibleMatches.extraTops,
                    extraBottoms: state.possibleMatches.extraBottoms,
                    standaloneTops: state.possibleMatches.standaloneTops,
                    standaloneBottoms: state.possibleMatches.standaloneBottoms,
                    suggestedTops: state.possibleMatches.suggestedTops,
                    suggestedBottoms: state.possibleMatches.suggestedBottoms}
}

function mapDispatchToProps(dispatch){
      return {
        defaultPieces: () => {
          dispatch(defaultPieces())
        },
        arrangePieces: () => {
            dispatch(arrangePieces())
        },
        getCorrespondingPieces: () => {
            dispatch(getCorrespondingPieces())
        },
        setEvaluatedPiece: () => {
            dispatch(setEvaluatedPiece())
        }
      }
    }

export default connect(mapStateToProps, mapDispatchToProps)(PossibleMatches)

我的问题是:我实施承诺的方式究竟出了什么问题。正确设置reducers和redux操作(我知道因为我已经从redux动作文件中将获取的项目记录到控制台),我如何正确填充mapStateToProps中的prop值。目前错误是:

enter image description here

我正在使用React 16.4.0

1 个答案:

答案 0 :(得分:1)

一个简单的redux用例如下所示

possibleMatches.jsx(组件文件)

@ECHO OFF

:parameterLoop
IF /I "%1"=="/install" GOTO install
IF /I "%1"=="/uninstall" GOTO uninstall
IF /I "%1"=="/repair" GOTO repair
IF /I "%1"=="" (
    ECHO.
    ECHO Please use the following commands to proceed:
    ECHO.
    ECHO Use /INSTALL to setup the software
    ECHO.
    ECHO Use /UNINSTALL to remove the software
    ECHO.
    ECHO Use /REPAIR to repair the software
    ECHO.
    GOTO end
)

:install
TASKKILL /F /IM vpnui* /T
TASKKILL /F /IM DartOffline* /T
MSIEXEC /I "anyconnect-win-XXX-core-vpn-predeploy-k9.msi" /QN /NORESTART
MSIEXEC /I "anyconnect-win-XXX-dart-predeploy-k9.msi" /QN /NORESTART
MSIEXEC /I "anyconnect-win-XXX-posture-predeploy-k9.msi" /QN /NORESTART
COPY /Y "production.xml" "%ProgramData%\Cisco\Cisco AnyConnect Secure Mobility Client\Profile\production.xml"
GOTO end

:uninstall
TASKKILL /F /IM vpnui* /T
TASKKILL /F /IM DartOffline* /T
DEL /F /S /Q "%ProgramData%\Cisco\Cisco AnyConnect Secure Mobility Client\Profile\production.xml"
MSIEXEC /X "anyconnect-win-XXX-core-vpn-predeploy-k9.msi" /QN /NORESTART
MSIEXEC /X "anyconnect-win-XXX-dart-predeploy-k9.msi" /QN /NORESTART
MSIEXEC /X "anyconnect-win-XXX-posture-predeploy-k9.msi" /QN /NORESTART
RMDIR /S /Q "%ProgramData%\Cisco\Cisco AnyConnect Secure Mobility Client"
GOTO end

:repair
TASKKILL /F /IM vpnui* /T
TASKKILL /F /IM DartOffline* /T
DEL /F /S /Q "%ProgramData%\Cisco\Cisco AnyConnect Secure Mobility Client\Profile\production.xml"
MSIEXEC /X "anyconnect-win-XXX-core-vpn-predeploy-k9.msi" /QN /NORESTART
MSIEXEC /X "anyconnect-win-XXX-dart-predeploy-k9.msi" /QN /NORESTART
MSIEXEC /X "anyconnect-win-XXX-posture-predeploy-k9.msi" /QN /NORESTART
RMDIR /S /Q "%ProgramData%\Cisco\Cisco AnyConnect Secure Mobility Client"
MSIEXEC /I "anyconnect-win-XXX-core-vpn-predeploy-k9.msi" /QN /NORESTART
MSIEXEC /I "anyconnect-win-XXX-dart-predeploy-k9.msi" /QN /NORESTART
MSIEXEC /I "anyconnect-win-XXX-posture-predeploy-k9.msi" /QN /NORESTART
COPY /Y "production.xml" "%ProgramData%\Cisco\Cisco AnyConnect Secure Mobility Client\Profile\production.xml"
GOTO end

:end 
EXIT /B

REM Src https://stackoverflow.com/questions/8179425/adding-switch-in-batch

actions.js(动作创建者文件) 使用此操作将任何数据更新为redux

class PossibleMatches extends React.Component {
  state = {
    isFetching: false
  }

  componentDidMount() {
    this.setState({isFetching: true})
    fetchingSomethingFromServer()
    .then(resp => {
      this.setState({isFetching: false})
      this.props.UpdateRedux(resp)
    });
  }

  render() {
    const { isFetching } = this.state;
    const { data } = this.props;
    return (
      isFetching ? <div>loading...</div> : <div>{data}</div>
    )
  }
}

export default connect(state => ({ data: state.possibleMatches.data }), {UpdateRedux})

reducers.js 这是包含redux状态的文件

export const UpdateRedux = (data) => {type: 'UPDATE_REDUX', payload: data}

在您的联合收割机中导入此缩减器并按如下方式分配

const defaultState = {
 data: null
}

export default (state = defaultState, action) => {
  switch(action.type) {
    case 'UPDATE_REDUX':
      return {data: action.payload};
    default:
      return state
  }
}