Реактивный список примитивов не перерисовывается должным образом - PullRequest
0 голосов
/ 09 сентября 2018

Почему действие заменителя filterPlayers () не вызывает повторную визуализацию? Я думал, что в случае с приставкой каждый раз, когда я пропускаю действие, он будет перерисовывать связанный компонент. Разве это не так, как это работает?

Чтобы попытаться обойти визуальные элементы без обновления, я попытался использовать componentDidUpdate и протестировать playerListFilterType prop на предмет изменений. Сама функция фильтра работает, я также заметил, что если я выберу следующий фильтр, мой визуальный список обновится, чтобы показать предыдущий отфильтрованный список.

Быстрая разбивка:

Я добавляю свойство класса visiblePlayers, которое содержит список игроков для отображения на экране.

Я заполняю свойство следующей функцией:

  getVisiblePlayers = () => {
    this.visiblePlayers = this.props.playerList.filter(player => player.visible === true)
  }

При нажатии кнопки я запускаю действие переупорядочения, которое настраивает свойство видимости для каждого игрока, однако это не вызывает повторного рендеринга (почему?) Экрана, поэтому для облегчения захвата обновления я использую метод componentDidUpdate () :

  componentDidUpdate(prevProps) {
    if (prevProps.playerListFilterType !== this.props.playerListFilterType) {
      this.getVisiblePlayers()
    }
  }

Затем я просто передаю visiblePlayers в PlayerList, который обеспечивает вывод данных на экран

<PlayerList
      playerList={this.visiblePlayers}
      fetchingData={this.props.fetchingData}
      handleDataRequest={this.fetchPlayersAsync} />

Когда я выполняю код в отладчике, я нажимаю точку останова в getVisiblePlayers() при нажатии кнопки фильтра. Я также вижу правильный список в this.visiblePlayers, когда getVisiblePlayers заканчивается, однако он не входит в метод render () после этого, и я предполагаю, почему в моем списке показаны результаты предыдущего фильтра.

Вот как выглядит полный код:

  class PlayerListScreen extends React.Component {

  static navigationOptions = ({ navigation }) => {
    return {
      headerTitle: navigation.getParam('headerButton'),
      headerRight: <Ionicons name='md-more' size={25} style={{ marginRight: 20 }} />
    }
  }

  async componentDidMount() {
    await this.fetchPlayersAsync();
  }

  componentDidUpdate(prevProps) {
    if (prevProps.playerListFilterType !== this.props.playerListFilterType) {
      this.getVisiblePlayers()
    }
  }

  setNavigationParams = () => {
    this.props.navigation.setParams({
      headerButton: this.headerButton
    })
  }

  // navigation header element
  headerButton = () => (
    <NavigationHeaderTitle
      handleDataRequest={this.fetchPlayersAsync}
      titleMessage={
        (this.props.fetchingData)
          ? 'fetching list of players'
          : `${this.props.playerList.length} online`
      } />
  )

  fetchPlayersAsync = async () => {
    await this.props.fetchPlayerListAsync();
    this.getVisiblePlayers()
    this.setNavigationParams()
  }

  visiblePlayers = []
  getVisiblePlayers = () => {
    this.visiblePlayers = this.props.playerList.filter(player => player.visible === true)
  }

  render() {
    return (
      <View>
        <PlayerListOptionsBar
          handleFiltering={this.props.filterPlayers}
          playerList={this.props.playerList} />

        <PlayerList
          playerList={this.visiblePlayers}
          fetchingData={this.props.fetchingData}
          handleDataRequest={this.fetchPlayersAsync} />
      </View>
    )
  }
}

const mapStateToProps = state => {
  return {
    fetchingData: state.player.fetchingData,
    playerList: state.player.playerList,
    playerListFilterType: state.player.playerListFilterType
  }
};

export default connect(mapStateToProps, { fetchPlayerListAsync, filterPlayers })(PlayerListScreen)
...