我正在构建我的第一个反应原生应用程序。我正在使用Firebase,Redux和React Native来构建我的应用程序。
我正在使用 thunk 从我的数据库中获取数据,我想用这些数据设置组件的本地状态。
当我在渲染函数中控制台.log(this.props.room)时,我可以看到数据库中的数据,但它没有被添加到组件DidMount()中的本地状态,所以我知道我的thunk和后端工作正常。
我认为我的组件在组件 DidMount 函数中设置我的本地状态之前正在渲染。有没有办法防止它在 this.setState() 运行时呈现?我的代码如下。还是这个.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)```
这是因为 setState 操作是异步的,并且会进行批处理以提高性能。这在 setState 的文档中进行了解释。
setState() 不会立即改变 this.state,但会创建一个 挂起的状态转换。调用此状态后访问此状态 方法可能会返回现有值。没有 保证对 setState 的调用的同步操作,并且调用可能 进行批处理以提高性能。
所以你可以做这样的事情,
this.setState({foo: 'bar'}, () => {
// Do something here.
});
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(全局状态),因此您不必将其添加到本地状态中。你可以直接从道具中访问房间的价值。