在Redux中的应用安装上设置存储状态

时间:2019-01-04 11:02:38

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

这是我的代码:

UI

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)

UI

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;
    }
};

如果我运行上面的代码,则会出现此错误:

  

错误:减速器执行时,您不得调用store.getState()。减速器已经接收到该状态作为参数。从顶部减速器将其传递下来,而不是从商店中读取。

     

onLoad   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 | 
  

App / _this.setUser / <   src / AppUI.jsx:38

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

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

1 个答案:

答案 0 :(得分:1)

我最终删除了reducers和actions,并且这样做了:

容器:

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)

UI:

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的成就