Javascript React-won';重新加载状态更改时重新加载

Javascript React-won';重新加载状态更改时重新加载,javascript,reactjs,redux,Javascript,Reactjs,Redux,在react应用程序中,我有一个从Redux商店获取的数据到某个组件的映射 {this.props.team && this.props.team.map((value: User, index: number) => (<Card key={index} className="team-card"> <C

在react应用程序中,我有一个从Redux商店获取的数据到某个组件的映射

{this.props.team && this.props.team.map((value: User, index: number) =>
                                    (<Card key={index} className="team-card">
                                        <CardMedia style={{
                                            backgroundImage: `url(${value.photoURL})`
                                        }} />
                                        <Typography use={"headline4"}>{value.displayName}</Typography>
                                        <Typography use={"body1"}>{value.description}</Typography>
                                        <CardActions>
                                            <CardActionButtons>
                                                {/* TODO: Add the ability to go to About to a specific team member card */}
                                                <CardActionButton>Vezi profilul</CardActionButton>
                                            </CardActionButtons>
                                        </CardActions>
                                    </Card>)
                                )}
这里还有负责该存储属性更新的reducer

export default function userReducer(state: Readonly<MetadataState> | undefined = initialAppState.metadata, action: MetadataActions): MetadataState {
    switch (action.type) {
        case 'TEAM_RECIEVED': return { ...state, team: action.payload };
        default: return state;
    }
}

您的异步操作有缺陷。特别是本守则:

team.forEach(async (val: User, index: number) => mappedTeam.push({
        ...val,
        photoURL: val.photoURL !== null ? URL.createObjectURL(await 
           fetch(val.photoURL!!).then(res => res.blob())) : null
    }));
将在将来的某个时候在任何操作之外异步改变存储状态。这是不允许的。试试这个版本

export function retrieveTeam() {
    return async (dispatch: Dispatch) => {

        const team = await getTeam_firestore();
        const mappedTeam: User[] = await Promise.all(team.map(
            async (val: User, index: number) => {
              const result = {...val};
              if (result.photoURL !== null) {
                const response = await fetch(result.photoURL);
                const blob = await response.blob();
                result.photoURL = URL.createObjectURL(blob);
              }
              return result;
        }));

        console.log('Got team')

        return dispatch({
            type: 'TEAM_RECIEVED',
            payload: mappedTeam
        })
    }
}
此版本在发送TEAM_Received操作之前等待异步获取

再解释一下:

foreach(异步函数)将只对一组异步工作进行排队,但foreach将立即返回。您需要等待所有的异步工作。所以不能使用array.foreach()。解决方案是以下两种模式之一:

假设您有以下方法:

async function getValWithPhoto(val) {
  const result = {...val};
  if (result.photoURL !== null) {
     const response = await fetch(result.photoURL);
     const blob = await response.blob();
     result.photoURL = URL.createObjectURL(blob);
  }
  return result;
}
模式1-以串行顺序运行每个异步提取(一次一个): 模式2-并行运行所有获取作业(同时)(我在上面的回答中所做的):
显示您的
mapStateToProps()
以及相应的减速器。当您的道具发生更改时,您的组件应该重新渲染。如果由于某种原因没有发生,请将道具置于状态,并在道具更改为手动处理渲染时更新状态。@AlexanderStaroselsky如果您在
state.metadata.team
中记录
MapStateTrops()
,则我已经添加了道具,您看到数据发生了更改吗?我注意到您的mapStatetoProps对某些字段使用了async/await。你不能这样做。mapStateToProps必须完全同步。如果您有异步工作,请在异步操作中执行,并使用结果更新redux状态…谢谢!这起作用了。但你能不能再进一步解释一下为什么会这样?我发现主要的区别在于使用if
Promise.all
(从未使用过它,所以我真的不明白它是如何工作的)。我理解您的解决方案的问题在于,我也一直在等待获取,没有使用
Promise.all
export function retrieveTeam() {
    return async (dispatch: Dispatch) => {

        const team = await getTeam_firestore();
        const mappedTeam: User[] = await Promise.all(team.map(
            async (val: User, index: number) => {
              const result = {...val};
              if (result.photoURL !== null) {
                const response = await fetch(result.photoURL);
                const blob = await response.blob();
                result.photoURL = URL.createObjectURL(blob);
              }
              return result;
        }));

        console.log('Got team')

        return dispatch({
            type: 'TEAM_RECIEVED',
            payload: mappedTeam
        })
    }
}
async function getValWithPhoto(val) {
  const result = {...val};
  if (result.photoURL !== null) {
     const response = await fetch(result.photoURL);
     const blob = await response.blob();
     result.photoURL = URL.createObjectURL(blob);
  }
  return result;
}
const mappedTeam = [];
for (const val of team) {
  const mappedVal = await getValWithPhoto(val);
  mappedTeam.push(mappedVal);
}

return dispatch(...);
const arrayOfPromises = team.map(val => getValWithPhoto(val));
// Use Promise.all() to turn the array of promises into a single
// promise: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
const promise = Promise.all(arrayOfPromises);
// now await that promise, which will return array of results
const mappedTeam = await promise;
return dispatch(...);