Почему рендеринг компонента до того, как this.setState () завершил установку состояния? - PullRequest
0 голосов
/ 19 января 2019

Я создаю свое первое реагирующее нативное приложение. Я использую Firebase, Redux и React Native для создания своего приложения.

Я использую thunk для извлечения данных из моей базы данных, и я хочу установить локальное состояние моего компонента с этими данными.

Когда я console.log (this.props.room) в функции рендеринга, я вижу данные из моей базы данных, но они не добавляются в локальное состояние в componentDidMount (), поэтому я знаю, что мой thunk и бэкэнд работает правильно.

Я думаю, что мой компонент рендерится до того, как моё локальное состояние установлено в функции 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)```

Ответы [ 2 ]

0 голосов
/ 19 января 2019
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 (глобальное состояние), вам не нужно добавлять его в локальное состояние.Вы можете напрямую получить доступ к стоимости комнаты из реквизита.

0 голосов
/ 19 января 2019

Это связано с тем, что действия setState являются асинхронными и пакетируются для повышения производительности. Это объясняется в документации setState.

setState () не изменяет немедленно this.state, но создает переход в состояние ожидания. Доступ к this.state после вызова этого Метод потенциально может вернуть существующее значение. Здесь нет гарантия синхронной работы звонков в setState и звонки могут быть побежденным для повышения производительности.

Так что вы можете сделать что-то вроде этого,

this.setState({foo: 'bar'}, () => { 
// Do something here. 
});
...