【问题标题】:Setting a store state on app mount in Redux在 Redux 中设置应用挂载的 store 状态
【发布时间】:2019-01-04 19:52:26
【问题描述】:

这是我的代码:

用户界面

export default class App extends Component {
    constructor(p) {
        super(p);
        this.state = {user: null};
    }

    setUser = () => {
        const {uid} = firebase.auth().currentUser;
        firebase.database().ref('Users').child(uid).on('value', r => {
            const user = r.val();
            this.setState({user: user});
            this.props.onLoad(this.state.user); // This is the problem
        });
    };

    componentWillMount() {
        if (firebase.auth().currentUser) {
            this.setUser();
        }
        firebase.auth().onAuthStateChanged(async () => {
            if (!firebase.auth().currentUser) {
                return null;
            }
            this.setUser();
        });
    }


    render() {
        return (
            <div className="App">
                <Nav/>
            </div>
        );
    }
}

容器

const mapStateToProps = state => ({user: state.user});
const mapDispatchToProps = dispatch => ({
    onLoad(user) {
        dispatch(setUser(user))
    }
});

export default connect(mapStateToProps, mapDispatchToProps)(App);

所以我要做的是在组件安装后立即设置一个商店。它一直有效,直到在此应用程序中进行更改。如果我更改数据库中的数据,我的应用程序中的数据会毫无问题地更新。

如果我尝试运行它:

容器:

import {setLevel} from "../../../../../actions";
import LevelSelectUI from '../../../ui/mainUI/levelSelectUI/LevelSelectUI';

const mapStateToProps = (state, props) => ({
    user: props.user
});

const mapDispatchToProps = dispatch => ({
    onLevelChange(uid, value) {
        dispatch(setLevel(uid, value));
    }
});

export default connect(mapStateToProps, mapDispatchToProps)(LevelSelectUI)

用户界面

export default ({user = {}, onLevelChange = f => f}) => {
    const lvls = [{
        db: 'Podstawówka',
        text: 'PODSTAWOWA',
    }, {
        db: 'Gimnazjum',
        text: 'GIMNAZJALNA',
    }, {
        db: 'Liceum',
        text: 'ŚREDNIA',
    }];
    let options = [];
    if (!user.level) {
        options.push(<option key={options.length} value={null}>WYBIERZ POZIOM</option>)
    }
    options = options.concat(lvls.map((lvl, i) => {
        return (
            <option key={(i + 1) * 2} value={lvl.db}>{`SZKOŁA ${lvl.text}`}</option>
        )
    }));
    return (
        <select value={user.level}
                onChange={e => onLevelChange(e.target.value)}>
            {/*onChange={(e) => console.log(e.target.value)}>*/}
            {options.map(opt => opt)}
        </select>
    )
}

行动:

export const setLevel = (value = '') => ({
    type: C.SET_LEVEL,
    payload: value,
});

减速器:

export const level = (state = {}, action) => {
    switch (action.type) {
        case C.SET_LEVEL:
            return firebase.database().ref('Users').child(firebase.auth().currentUser.uid).child('level').set(action.payload).catch(e => console.log(e));
        default:
            return state;
    }
};

如果我运行上面的代码,我会得到这个错误:

错误:你不能在 reducer 执行时调用 store.getState()。 reducer 已经接收到状态作为参数。从顶部 reducer 向下传递,而不是从 store 中读取。

加载 src/AppContainer.jsx:8

   5 | const mapStateToProps = state => ({user: state.user});
   6 | const mapDispatchToProps = dispatch => ({
   7 |     onLoad(user) {
>  8 |         dispatch(setUser(user))
   9 |     }
  10 | });
  11 | 

应用程序/_this.setUser/

  35 |         //         else this.setState({assignedWork: undefined});
  36 |         //     });
  37 |         // }
> 38 |         this.props.onLoad(this.state.user);
     | ^  39 |     });
  40 | };
  41 | 

所以我假设我的做法是错误的。但是如何将状态设置为等于数据库中的数据?我尝试在商店初始化中这样做,但它只是出错了。

【问题讨论】:

  • 你不应该在减速器中使用firebase.database().ref('Users').child(firebase.auth().currentUser.uid).child('level').set(action.payload).catch(e =&gt; console.log(e));
  • 所以把它付诸行动?
  • 是的,把它放在动作创建器(thunk)中,然后把它的结果保存在减速器中

标签: javascript reactjs firebase-realtime-database redux react-redux


【解决方案1】:

我最终删除了减速器和动作,然后这样做了:

容器:

const mapStateToProps = (state, props) => ({
    user: props.user
});

const mapDispatchToProps = () => ({
    onLevelChange(value) {
        firebase.database().ref('Users').child(firebase.auth().currentUser.uid).child('level').set(value).catch(e => console.log(e));
    }
});

export default connect(mapStateToProps, mapDispatchToProps)(LevelSelectUI)

用户界面:

export default ({user = {}, onLevelChange = f => f}) => {
    const lvls = [{
        db: 'Podstawówka',
        text: 'PODSTAWOWA',
    }, {
        db: 'Gimnazjum',
        text: 'GIMNAZJALNA',
    }, {
        db: 'Liceum',
        text: 'ŚREDNIA',
    }];
    let options = [];
    if (!user.level) {
        options.push(<option key={options.length} value={null}>WYBIERZ POZIOM</option>)
    }
    options = options.concat(lvls.map((lvl, i) => {
        return (
            <option key={(i + 1) * 2} value={lvl.db}>{`SZKOŁA ${lvl.text}`}</option>
        )
    }));
    return (
        <select value={user.level}
                onChange={e => onLevelChange(e.target.value)}>
            {/*onChange={(e) => console.log(e.target.value)}>*/}
            {options.map(opt => opt)}
        </select>
    )
}

感谢 Manjeet Singh 的 leed

【讨论】:

    猜你喜欢
    • 2019-08-10
    • 1970-01-01
    • 2016-07-14
    • 1970-01-01
    • 1970-01-01
    • 2019-02-26
    • 1970-01-01
    • 1970-01-01
    • 2020-10-21
    相关资源
    最近更新 更多