为什么组件渲染在这.setState() 完成状态设置之前



我正在构建我的第一个反应原生应用程序。我正在使用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(全局状态),因此您不必将其添加到本地状态中。你可以直接从道具中访问房间的价值。

相关内容

  • 没有找到相关文章

最新更新