【问题标题】:react-native re-render negates filterreact-native 重新渲染否定过滤器
【发布时间】:2020-01-03 13:52:13
【问题描述】:

为了了解自己的 react-native,我正在构建一个应用程序,其中包含一个在 redux 的帮助下填充票证的 FlatList。当我尝试通过输入数字来过滤票证时,列表会被过滤但仅持续 1 秒。之后,它再次给出所有票的列表。我很难找到初学者代码背后的逻辑错误。任何帮助将不胜感激。

我粘贴了下面的列表:

const AllTicketList = ({ navigation, ticket: { allTickets }, getTickets }) => {
  useEffect(() => {
    getTickets();
  }, []);

  const [enteredValue, setEnteredValue] = useState();
  const [selectedNumber, setSelectedNumber] = useState(false);
  const [displayedTickets, setDisplayedTickets] = useState();
  const [confirmed, setConfirmed] = useState(false);

  useEffect(() => {
    setDisplayedTickets(allTickets);
  });

  const confirmInputHandler = () => {
    const chosenNumber = parseInt(enteredValue);
    if (isNaN(chosenNumber) || chosenNumber <= 0) {
      Alert.alert(
        'Invalid number',
        'The number of upvotes has to be greater than 0.',
        [{ text: 'Ok', style: 'destructive', onPress: resetInputHandler }]
      );
      return;
    }

    setConfirmed(true);
    setSelectedNumber(chosenNumber);
    Keyboard.dismiss();
  };

  const resetInputHandler = () => {
    setEnteredValue('');
    setConfirmed(false);
  };

  const numberInputHandler = inputText => {
    setEnteredValue(inputText.replace(/[^0-9]/g, ''));
  };

  if (confirmed) {
    const foundTickets = displayedTickets.filter(t => t.numberOfVotes >= selectedNumber);
    setDisplayedTickets(foundTickets);
    setConfirmed(false);
  }

  return (
    <View>
      <SearchBarUpvotes
        numberInputHandler={numberInputHandler}
        confirmInputHandler={confirmInputHandler}
        enteredValue={enteredValue}
      />
      <FlatList
        removeClippedSubviews={false}
        data={displayedTickets}
        renderItem={({ item }) => (
          <TicketItem ticket={item} navigation={navigation} />
        )}
        keyExtractor={item => item.id}
      />
    </View>
  );
};

const mapStateToProps = state => ({
  ticket: state.ticket
});

export default connect(mapStateToProps, {
  getTickets
})(AllTicketList);

【问题讨论】:

    标签: react-native react-redux react-native-flatlist


    【解决方案1】:

    问题出在你的第二个useEffect 钩子上:

    useEffect(() => {
      setDisplayedTickets(allTickets);
    });
    

    此效果,将在每次重新渲染时将displayedTickets 设置为allTickets

    这就是发生的事情:
    1. 当您过滤工单时,您正在更改状态,并将displatedTickets 设置为过滤后的工单:setDisplayedTickets(foundTickets);
    2. displayedTickets 被更新,组件被重新渲染,你会看到一秒钟的新票,一旦重新渲染,效果就会再次执行,它将displayedTickets 设置为@987654329再次@:setDisplayedTickets(allTickets);

    所以这是我的建议:
    1. 删除第二个useEffect - 这将阻止displayedTickets 在每次重新渲染时再次设置为allTickets。 2. 在您的平面列表中将数据更改为displayedTickets || allTickets。这样,当工单未过滤时 - 列表将显示allTickets,一旦您过滤它们,列表将显示displayedTickets

    你的最终代码应该是这样的:

    const AllTicketList = ({ navigation, ticket: { allTickets }, getTickets }) => {
      useEffect(() => {
        getTickets();
      }, []);
    
      const [enteredValue, setEnteredValue] = useState();
      const [selectedNumber, setSelectedNumber] = useState(false);
      const [displayedTickets, setDisplayedTickets] = useState();
      const [confirmed, setConfirmed] = useState(false);
    
      // Remove this effect
      //useEffect(() => {
      //  setDisplayedTickets(allTickets);
      //});
    
      const confirmInputHandler = () => {
        const chosenNumber = parseInt(enteredValue);
        if (isNaN(chosenNumber) || chosenNumber <= 0) {
          Alert.alert(
            'Invalid number',
            'The number of upvotes has to be greater than 0.',
            [{ text: 'Ok', style: 'destructive', onPress: resetInputHandler }]
          );
          return;
        }
    
        setConfirmed(true);
        setSelectedNumber(chosenNumber);
        Keyboard.dismiss();
      };
    
      const resetInputHandler = () => {
        setEnteredValue('');
        setConfirmed(false);
      };
    
      const numberInputHandler = inputText => {
        setEnteredValue(inputText.replace(/[^0-9]/g, ''));
      };
    
      if (confirmed) {
        const foundTickets = displayedTickets.filter(t => t.numberOfVotes >= selectedNumber);
        setDisplayedTickets(foundTickets);
        setConfirmed(false);
      }
    
      return (
        <View>
          <SearchBarUpvotes
            numberInputHandler={numberInputHandler}
            confirmInputHandler={confirmInputHandler}
            enteredValue={enteredValue}
          />
          <FlatList
            removeClippedSubviews={false}
            data={displayedTickets || allTickets} /* <-- displayedTickets || allTickets instead of displayedTickets */
            renderItem={({ item }) => (
              <TicketItem ticket={item} navigation={navigation} />
            )}
            keyExtractor={item => item.id}
          />
        </View>
      );
    };
    
    const mapStateToProps = state => ({
      ticket: state.ticket
    });
    
    export default connect(mapStateToProps, {
      getTickets
    })(AllTicketList);
    

    【讨论】:

      猜你喜欢
      • 2019-09-26
      • 2018-12-27
      • 1970-01-01
      • 2022-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-06-20
      • 2021-11-18
      相关资源
      最近更新 更多