Установка состояния магазина при монтировании приложения в Redux - PullRequest
0 голосов
/ 04 января 2019

Это мой код:

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 | 
* 1 034 * 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 голосов
/ 04 января 2019

Я закончил тем, что удалил редукторы и действия и просто сделал:

контейнер:

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Сингх для лид

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...