Reactjs 如何使用React.createContext包装器在我的特殊情况下执行此Redux Thunk操作创建者

Reactjs 如何使用React.createContext包装器在我的特殊情况下执行此Redux Thunk操作创建者,reactjs,redux,Reactjs,Redux,我学习React Redux和Thunk,我需要这个动作创建者使用上下文 我有一个Redux操作asyncSaveUser,它的工作原理如下: const asyncSaveUser = () => { return async dispatch => { dispatch(saveUserStart()); ....Do lots of stuff... }; export default asyncSaveUser; 但我需要它看起来像

我学习React Redux和Thunk,我需要这个动作创建者使用上下文

我有一个Redux操作
asyncSaveUser
,它的工作原理如下:

const asyncSaveUser = () => {
    return async dispatch => {
        dispatch(saveUserStart());
        ....Do lots of stuff...
};

export default asyncSaveUser;
但我需要它看起来像这样:(Wrappen在
中使用Firebase

但当我这样做时,Redux Thunk不会检测到
asyncSaveUser
是动作创建者,也不会调用它`

Firebase的
上下文:

import React from 'react';

const FirebaseContext = React.createContext(null);

export const withFirebase = Component => props => (
    <FirebaseContext.Consumer>{firebase => <Component {...props} firebase={firebase} />}</FirebaseContext.Consumer>
);

export default FirebaseContext;
因此,只有一个
新的Firebase()
类。可以说是辛格尔顿风格!。 因此,访问它的唯一方法是通过
withFirebase(asyncSaveUser)

我知道我的问题来自于用Firebase将操作包装在
中,因此
asyncSaveUser
Thunk不再是Thunk

那么,我如何访问我的
Firebase
提供商
?我必须从头开始重新设计吗

更新

我已经尝试了以下代码,它一直运行良好:
使用Firebase返回(保存)之后,在
save()
中不会命中断点。我看起来像是返回了一个
const save=({…
对象,但是它里面的代码没有运行,所以这可能就是它不工作的原因

const asynsaveUser = () => {
    return dispatch => {
        const save = ({ firestore }) => {
            const userRef = firestore.userDoc(firestore.auth.currentUser.uid);
            dispatch(saveUserStart());
            firestore.db
                .runTransaction(transaction => {
                    // This code may get re-run multiple times if there are conflicts.
                    return transaction.get(userRef).then(doc => {
                        if (!doc.exists) {
                            return Promise.reject('Transaction failed: User dont exist!');
                        }
                        const newRoles = doc.data().roles;
                        // new roll
                        newRoles.push(ROLES.USER);
                        // remove roll
                        newRoles.splice(newRoles.indexOf('ANONYMOUS'), 1);
                        // save it back
                        transaction.update(userRef, { roles: newRoles });
                        return newRoles;
                    });
                })
                .then(newRoles => {
                    dispatch(saveUserSuccess(firestore.auth.currentUser));
                    console.log(`Transaction successfully committed role(s): ${newRoles}`);
                })
                .catch(error => {
                    dispatch(saveUserFailure(error));
                    console.log(error);
                });
        };

        return withFirebase(save);
    };
};

export default asynsaveUser ;
我在这张图片中将
asynSaveUser
重命名为
saveUser


希望您能理解,请给出建议?

问题是,我不明白,当您使用Redux-Action和Redux-Reducer类型的方法时,为什么需要上下文提供者和上下文使用者方法

此外,还有一些错误。 我注意到的第一件事是: 高阶组件在其参数中需要一个组件,而不是动作创建者

高阶组件向组件添加额外属性(React
props

您在这里试图实现的目标已经由
react redux
npm包提供的
connect
HOC完成

export const asyncSaveUser=({firestore})=>dispatch=>{
const userRef=firestore.userDoc
...
//不要用Firebase做任何退货
//只需分派此操作创建者必须执行的相应操作
//也就是说,不再需要return语句,除非您想退出执行
//这个功能的
//例如:
调度({你好:'你好',很好:'相同'});
} 
现在,在您的
index.js
App.js
文件中,或您要求
react
调用
您的
react
应用程序的任何位置

你只需要这个


现在假设您有一个组件
Hello.js

从“React”导入React
从“/firebase”导入{firestore};
从'react redux'导入{connect};
从“../../redux/actionCreators/asyncSaveUser.js”导入{asyncSaveUser};
功能你好(道具){
返回(props.asyncSaveUser({firestore}}>Hello);
}
常量mapStateToProps=(状态)=>{
返回{};
}
const mapDispatchToProps=(调度)=>{
返回{
asyncSaveUser:(stuff)=>dispatch(asyncSaveUser(stuff)),
}
}
导出默认连接(mapStateToProps、mapDispatchToProps)(您好);
问题是你可以制作一个只向你的组件添加
firebase
道具的HOC,在这个HOC中,你仍然会使用
react redux
中的
connect
函数,所以…,制作它并没有什么意义,因为它会在你的
组件树中添加不必要的组件,并阻碍性能曼斯


希望这是有意义的,或者是有价值的。

Uhmm,我不确定,但是您刚刚在一个更高阶的组件中传递了一个action creator。您应该首先将您的
asyncSaveUser
操作放在上下文中。并且您应该
导出默认asyncSaveUser
React.createContext({asyncSaveUser})
然后使用创建的上下文。不确定如何执行该操作,“您应该首先将asyncSaveUser操作放在上下文中。”.通常使用HOC是直接的,只是包装它们,而不是这个time@RishabhAnand如果您有时间,可以创建并回答解释此问题吗?我用更多的代码和文本更新了我的问题。感谢好主意,我学到了很多。因为我用Firebase将此
新Firebase()
Singelton样式烘焙到我的
中(保存)
wrapper HOC所以我不想
props.asyncSaveUser({firestore})
无论如何,我在这里等待答案时最后做的是使用Thunk
和extraargument
像这样
const middleware=[Thunk.withExtraArgument(firebase),initialiseagamiddleware]当我为唯一的
新Firebase()
创建React.createContext时,我会在App root中这样做。不知道这是好是坏,也许我会运行一些测试
import Firebase, { FirebaseContext } from './firebase';
import store from './redux/store';

ReactDOM.render(
    <FirebaseContext.Provider value={new Firebase()}>
        <Provider store={store}>
            <App />
        </Provider>
    </FirebaseContext.Provider>,

    document.getElementById('root'),
);
const asynsaveUser = () => {
    return dispatch => {
        const save = ({ firestore }) => {
            const userRef = firestore.userDoc(firestore.auth.currentUser.uid);
            dispatch(saveUserStart());
            firestore.db
                .runTransaction(transaction => {
                    // This code may get re-run multiple times if there are conflicts.
                    return transaction.get(userRef).then(doc => {
                        if (!doc.exists) {
                            return Promise.reject('Transaction failed: User dont exist!');
                        }
                        const newRoles = doc.data().roles;
                        // new roll
                        newRoles.push(ROLES.USER);
                        // remove roll
                        newRoles.splice(newRoles.indexOf('ANONYMOUS'), 1);
                        // save it back
                        transaction.update(userRef, { roles: newRoles });
                        return newRoles;
                    });
                })
                .then(newRoles => {
                    dispatch(saveUserSuccess(firestore.auth.currentUser));
                    console.log(`Transaction successfully committed role(s): ${newRoles}`);
                })
                .catch(error => {
                    dispatch(saveUserFailure(error));
                    console.log(error);
                });
        };

        return withFirebase(save);
    };
};

export default asynsaveUser ;