Это мой код:
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 |
Так что я предполагаю, что мой способ сделать это просто неверен. Но как я могу установить состояние равным данным в базе данных? Я попытался сделать это при инициализации магазина, но он просто ошибся.