我正在构建我的第一个React本机应用程序。我正在使用Firebase,Redux和React Native来构建我的应用程序。
我正在使用thunk从数据库中获取数据,我想用该数据设置组件的本地状态。
当我在render函数中使用console.log(this.props.room)时,我可以看到数据库中的数据,但是没有将其添加到componentDidMount()的本地状态中,所以我知道我的重击和后端是工作正常。
我认为在componentDidMount函数中设置本地状态之前,我的组件正在渲染。有没有办法防止它在this.setState()运行时呈现?我的代码如下。还是this.setState无法正常工作的另一个原因?
import { connect } from 'react-redux';
import {
Image,
Platform,
ScrollView,
StyleSheet,
Text,
TouchableOpacity,
View,
TextInput
} from 'react-native';
import { submitIdea, getRoom } from '../redux/reducers/rooms/actions'
class RoomScreen extends React.Component {
static navigationOptions = {
title: 'Undecided!'
};
constructor(props) {
super(props)
this.state = {
currentUser: '',
submittedIdea: false,
currentUserIdea: '',
roomName: '',
ownerName: '',
peopleAndIdeas: [],
prompt: '',
room: {}
}
this.handleIdeaSubmit = this.handleIdeaSubmit.bind(this)
}
handleIdeaSubmit() {
const { user, roomName } = this.props.navigation.state.params
this.setState({ submittedIdea: true })
this.props.submitIdea(user, this.state.userIdea, roomName)
}
async componentDidMount() {
const { user, roomName } = this.props.navigation.state.params
await this.props.getRoom(roomName)
this.setState({
room: this.props.room
})
}
render() {
return (
<View style={styles.container}>
<ScrollView contentContainerStyle={styles.contentContainer}>
<View>
<Text>Room name: {this.state.room.name}</Text>
</View>
<View>
<Text>This room was created by: {this.state.room.owner}</Text>
</View>
<View>
<Text>What are we deciding? {this.state.room.prompt}</Text>
</View>
{/* checking whether or not the user has submitted an idea and altering the view */}
{!this.state.submittedIdea ?
<View style={styles.container}>
<TextInput
style={{ height: 40, borderColor: 'gray', borderWidth: 1 }}
onChangeText={(text) => this.setState({ userIdea: text })}
value={this.state.createRoomName}
placeholder="Enter your idea."
/>
<TouchableOpacity
style={styles.button}
onPress={this.handleIdeaSubmit}
>
<Text> Submit Idea. </Text>
</TouchableOpacity>
</View> :
<View>
<Text>Your idea was: {this.props.userIdea}</Text>
</View>
}
<View style={styles.getStartedContainer}>
<Text>IDEAS</Text>
</View>
<View>
<Text style={styles.getStartedText}>USERS</Text>
</View>
</ScrollView>
</View >
);
}
}
const mapStateToProps = state => ({
room: state.room.room
})
const mapDispatchToProps = (dispatch) => ({
getRoom: (roomName) => dispatch(getRoom(roomName)),
submitIdea: (user, idea, roomName) => dispatch(submitIdea(user, idea, roomName))
})
export default connect(mapStateToProps, mapDispatchToProps)(RoomScreen)```
答案 0 :(得分:2)
这是因为setState操作是异步的,并且为了提高性能而进行了批处理。在setState的文档中对此进行了解释。
setState()不会立即使this.state突变,而是创建一个 等待状态转换。调用此后访问this.state 方法可能会返回现有值。没有 保证对setState的调用的同步操作,并且调用可以 进行批量处理以提高性能。
所以你可以做这样的事情,
this.setState({foo: 'bar'}, () => {
// Do something here.
});
答案 1 :(得分:0)
async componentDidMount() {
const { user, roomName } = this.props.navigation.state.params
await this.props.getRoom(roomName)
this.setState({
room: this.props.room
})
}
在这种情况下,您不必使用本地状态。
render() {
const {room: {name}} = this.props;
return (
<View style={styles.container}>
<ScrollView contentContainerStyle={styles.contentContainer}>
<View>
<Text>Room name: {name}</Text>
</View>
</ScrollView>
</View>
)
}
在这里,因为您使用的是redux(全局状态),所以不必将其添加到本地状态。您可以通过道具直接访问房间的价值。