这是我的代码:
用户界面
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,
});
reducer :
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;
}
};
如果我运行上面的代码,我会收到此错误:
Error: You may not call store.getState() while the reducer is executing. The reducer has already received the state as an argument. Pass it down from the top reducer instead of reading it from the store.
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 |
所以我假设我的做法是错误的。但是如何将状态设置为等于数据库中的数据呢?我尝试在商店初始化中执行此操作,但它只是出错了。
最佳答案
我最终删除了 reducer 和操作,然后这样做了:
容器:
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为利德
关于javascript - 在 Redux 中设置应用挂载的存储状态,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54037712/