javascript - 尝试在 ComponentDidMount 中使用异步承诺填充道具
问题描述
所以在我不受控制的 PossibleMatches 组件内部,我从 React 的工作方式知道,初始渲染阶段将使用空的 prop 值(如果这些 prop 值依赖于外部应用程序状态(mapStateToProps))发生,无论我是否有 componentDidMount 生命周期方法或构造函数设置。作为对此的回应,我在 componentDidMount 中设置了一个 Promise,这样当我调度 prop 函数 [defaultPieces,arrangePieces] 时,我可以让 UI 呈现一个 ActivityIndicator 以指示当前正在获取的东西。问题是,当我从承诺的成功阶段调用 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);
})
}
}
UI 如何决定显示什么:
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>
);
}
My PossibleMatches 减速器
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)
我的问题是:我实现承诺的方式到底有什么问题。正确设置 reducer 和 redux 操作(我知道是因为我已经从 redux 操作文件将获取的项目记录到控制台),如何正确填充 mapStateToProps 中的 prop 值。目前的错误是:
我使用反应 16.4.0
解决方案
一个简单的 redux 用例如下所示
possibleMatches.jsx(组件文件)
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})
actions.js(动作创建者文件)使用此动作将任何数据更新到 redux
export const UpdateRedux = (data) => {type: 'UPDATE_REDUX', payload: data}
reducers.js 这是保存 redux 状态的文件
const defaultState = {
data: null
}
export default (state = defaultState, action) => {
switch(action.type) {
case 'UPDATE_REDUX':
return {data: action.payload};
default:
return state
}
}
在您的组合减速器中导入此减速器并将其分配如下
import possibleMatches from 'reducers.js';
combineReducers({ possibleMatches });
推荐阅读
- javascript - 我对 javascript 嵌套的 Promise 有一些问题
- node.js - 将来自 gmail 附件的文件存储在 Firebase 存储中
- python-3.x - 如何使用脚本获取文件
- javascript - props 未定义,尽管状态已更改
- php - 如何从 number_format 函数中删除 PHP 中的美分部分
- google-cloud-platform - JanusGraph 大规模数据摄取
- c# - 为什么有些 NuGet 包 dll 被复制到解决方案的输出目录而有些没有?
- linux - 如何以这样的方式组织 bash 文件,以便我可以使用文件夹来获得更好的结构,以便在“导入...路径”依赖项中使用?
- javascript - 如何合并两个不同的firebase项目?
- spring-security - Spring security @EnableOAuth2Sso - 我们不能跳过开发环境的自签名 ssl 连接