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

Я пытаюсь добавить фильтр в свое приложение, но по какой-то причине selectedValue в компоненте <Picker> не придерживается выбранной опции. Я вижу, как текст фильтра меняется со «всего» на «лобби» в левом верхнем углу, однако, как только список игроков полностью отображается, он снова становится «все». и playerListFilterType prop имеет значение undefined. Я прошел по коду в отладчике, и он остается «лобби», пока список не будет перерисован. Само действие работает, поэтому список показывает точные результаты.

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

import React from 'react'
import { View, Picker } from 'react-native'
import PlayerList from '../components/PlayerList'
import { fetchPlayerListAsync, filterPlayers } from '../redux/actions/player_actions';

import NavigationHeaderTitle from '../components/NavigationHeaderTitle'
import PlayerStatusFilterPicker from '../components/pickers/PlayerStatusFilterPicker'

import { connect } from 'react-redux'

class PlayerListScreen extends React.Component {

  static navigationOptions = ({ navigation }) => {
    const playerStatusFilterPicker = (
      <PlayerStatusFilterPicker
        playerListFilterType={navigation.getParam('playerListFilterType')}
        filterPlayers={navigation.getParam('filterPlayers')}
        playerList={navigation.getParam('playerList')}
      />
    )

    return {
      headerTitle: navigation.getParam('headerButton'),
      headerRight: playerStatusFilterPicker
    }
  }

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

  setNavigationParams = () => {
    this.props.navigation.setParams({
      headerButton: this.headerButton,
      playerList: this.props.playerList,
      playerListFilterType: this.props.playerListFilterType,
      filterPlayers: this.props.filterPlayers
    })
  }

  // 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.setNavigationParams()
  }

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

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

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

и вот как выглядит компонент фильтра, но я не думаю, что проблема заключается здесь:

import React, { Component } from "react";
import { 
  View,
  Picker
} from "react-native";
import * as constants from '../../constants'

class PlayerStatusFilterPicker extends Component {
  render() {
    return (
      <View>
        <Picker 
          selectedValue={this.props.playerListFilterType}
          onValueChange={(itemValue) => this.props.filterPlayers(itemValue, this.props.playerList)}
          style={{ height: 40, width: 100 }}
        >
          <Picker.Item label='all' value='all' />
          <Picker.Item label="lobby" value={constants.IN_LOBBY} />
          <Picker.Item label="in game" value={constants.IN_GAME} />
        </Picker>
      </View>
    );
  }
}
export default PlayerStatusFilterPicker;

Вот как выглядит редуктор:

    // show only the players that are waiting in the main lobby
case actionTypes.SHOW_PLAYERS_IN_LOBBY: {
  const filteredList = action.payload.filter(player => player.status === constants.IN_LOBBY)
  return { playerList: filteredList, playerListFilterType: constants.IN_LOBBY, fetchingData: false }
}

// show only the players that are currently playing
case actionTypes.SHOW_PLAYERS_IN_GAME: {
  const filteredList = action.payload.filter(player => player.status === constants.IN_GAME)
  return { playerList: filteredList, playerListFilterType: constants.IN_LOBBY, fetchingData: false }
}

enter image description here

1 Ответ

0 голосов
/ 07 сентября 2018

Исправлено с помощью метода жизненного цикла componentDidUpdate. Вот так:

componentDidUpdate(prevProps) {
if (this.props.playerListFilterType != prevProps.playerListFilterType) {
  this.props.navigation.setParams({
    playerListFilterType: this.props.playerListFilterType
  })
}

}

...