繁体   English   中英

如何更新 object 数组 State 和可触摸项目上的屏幕样式点击反应原生

[英]How to update object Array State and screen style on touchable item click in react native

我对本机反应有点新,我在更新 object 数组 State 和按钮项目上的屏幕样式时在反应本机运行时单击时遇到了困难

我尝试使用 useState 但在运行时点击可触摸项目时样式不会改变

请告诉我在项目单击时更改屏幕视图样式的正确方法

在下面查看我的代码

import React, {useState} from 'react';
import {ScrollView, FlatList, View, Text, TouchableOpacity} from 'react-native';

import styles from './styles';

export default function Loans({}) {
  const [selectedDurationId, setSelectedDurationId] = useState(1);
  const [selectedAmountId, setSelectedAmountId] = useState(1);

  const changeSelectedDuration = function (id) {
    console.log('before selected Duration');
    console.log(id);
    //change all the selecteds to no
    durationArray.forEach(function (arrayItem) {
      var x = (arrayItem.selected = 'no');
      console.log(x);
      setSelectedDurationId(id);
      updateDataArray(durationArray, selectedDurationId);
      console.log('after selected Duration');
    });
  };

  const changeSelectedAmount = function (id) {
    console.log('before selected Amount');
    console.log(id);
    //change all the selecteds to no
    loanAmountArray.forEach(function (arrayItem) {
      var x = (arrayItem.selected = 'no');
      console.log(x);
    });
    setSelectedAmountId(id);
    updateDataArray(loanAmountArray, selectedAmountId);
    console.log('after selected Amount');
  };

  const updateDataArray = function (array, id) {
    array.forEach(function () {
      //change selected to yes where id == id
      if (array.id === id) {
        var x = (array.selected = 'yes');
        console.log(x);
      }
    });
  };

  const loanAmountArray = [
    {
      id: 1,
      amount: '5,000',
      selected: 'yes',
    },
    {
      id: 2,
      amount: '10,000',
      selected: 'no',
    },
    {
      id: 3,
      amount: '20,000',
      selected: 'no',
    },
  ];

  const durationArray = [
    {
      id: 1,
      days: '30 days',
      rate: '3.3% Interest',
      selected: 'yes',
    },
    {
      id: 2,
      days: '60 days',
      rate: '5% Interest',
      selected: 'no',
    },
    {
      id: 3,
      days: '90 days',
      rate: '7% Interest',
      selected: 'no',
    },
  ];

  return (
    <View style={{flex: 1}}>
      <ScrollView>
        <View style={styles.contain}>
          <Text>Chose Loan Amount</Text>
          <FlatList
            numColumns={6}
            data={loanAmountArray}
            keyExtractor={(item, index) => {
              console.log('index', index);
              return index.toString();
            }}
            renderItem={({item}) => {
              console.log('item', item);
              return (
                <View>
                  <TouchableOpacity
                    onPress={() => {
                      changeSelectedAmount(item.id);
                    }}>
                    <Text
                      style={
                        item.selected === 'yes'
                          ? styles.textBoxSelected
                          : styles.textBox
                      }>
                      {item.amount}
                    </Text>
                  </TouchableOpacity>
                </View>
              );
            }}
          />

          <Text>Chose Payment Duration</Text>
          <FlatList
            numColumns={3}
            data={durationArray}
            keyExtractor={(item, index) => {
              console.log('index', index);
              return index.toString();
            }}
            renderItem={({item}) => {
              console.log('item', item);
              return (
                <View>
                  <TouchableOpacity
                    style={
                      item.selected === 'yes'
                        ? styles.durationViewPressed
                        : styles.durationView
                    }
                    onPress={() => {
                      changeSelectedDuration(item.id);
                    }}>
                    <View>
                      <Text style={styles.interest}>{item.rate}</Text>
                    </View>
                    <View>
                      <Text style={styles.days}>{item.days}</Text>
                    </View>
                  </TouchableOpacity>
                </View>
              );
            }}
          />
        </View>
      </ScrollView>
    </View>
  );
}

这是下面的样式

import {StyleSheet} from 'react-native';

export default StyleSheet.create({
  textBox: {
    marginTop: 13,
    marginBottom: 30,
    paddingTop: 10,
    paddingLeft: 16,
    paddingRight: 6,
    fontSize: 18,
    borderColor: '#1a2856',
    borderWidth: 5,
    borderTopLeftRadius: 20,
    borderTopRightRadius: 20,
    borderBottomLeftRadius: 20,
    borderBottomRightRadius: 20,
  },
  textBoxSelected: {
    marginTop: 13,
    marginBottom: 30,
    paddingTop: 10,
    paddingLeft: 16,
    paddingRight: 6,
    fontSize: 18,
    backgroundColor: '#1a2856',
    color: '#fff',
    borderWidth: 5,
    borderTopLeftRadius: 20,
    borderTopRightRadius: 20,
    borderBottomLeftRadius: 20,
    borderBottomRightRadius: 20,
  },
  durationView: {
    marginTop: 10,
    marginBottom: 20,
    paddingLeft: 5,
    paddingRight: 5,
  },
  durationViewPressed: {
    marginTop: 10,
    marginBottom: 20,
    paddingLeft: 5,
    paddingRight: 5,
    borderColor: '#1a2856',
    borderWidth: 5,
  },
  interest: {
    color: '#fff',
    backgroundColor: '#1a2856',
    paddingLeft: 5,
    paddingRight: 5,
  },
  days: {
    borderColor: '#1a2856',
    borderWidth: 5,
    paddingTop: 10,
    paddingLeft: 16,
    paddingRight: 6,
    fontSize: 18,
  },
});

问题

loanAmountArraydurationArray都在 function 主体中定义,因此它们实际上在每个渲染周期都重新声明,因此您认为在上一个渲染周期中所做的任何突变都将被清除。 发生这种情况时,样式属性永远无法匹配每次渲染的任何不同内容。

解决方案

  1. 由于您似乎并没有真正更新数组的元素,您可以将 arrays 移出组件。 它们可以保持const并且不会在每次渲染时重新声明。
  2. 不必费心尝试更新数组中每个元素的selected属性,您可以轻松地从selectedDurationIdselectedAmountId state 值和渲染时的当前item.id导出选定的 state。
  3. 使用extraData指示列表应该重新呈现。

代码:

const loanAmountArray = [
  {
    id: 1,
    amount: "5,000",
    selected: "yes"
  },
  {
    id: 2,
    amount: "10,000",
    selected: "no"
  },
  {
    id: 3,
    amount: "20,000",
    selected: "no"
  }
];

const durationArray = [
  {
    id: 1,
    days: "30 days",
    rate: "3.3% Interest",
    selected: "yes"
  },
  {
    id: 2,
    days: "60 days",
    rate: "5% Interest",
    selected: "no"
  },
  {
    id: 3,
    days: "90 days",
    rate: "7% Interest",
    selected: "no"
  }
];

export default function Loans({}) {
  const [selectedDurationId, setSelectedDurationId] = useState(1);
  const [selectedAmountId, setSelectedAmountId] = useState(1);

  const changeSelectedDuration = function (id) {
    setSelectedDurationId(id);
  };

  const changeSelectedAmount = function (id) {
    setSelectedAmountId(id);
  };

  return (
    <View style={{ flex: 1 }}>
      <ScrollView>
        <View style={styles.contain}>
          <Text>Chose Loan Amount</Text>
          <FlatList
            numColumns={6}
            data={loanAmountArray}
            extraData={selectedAmountId} // <-- prop used to rerender
            keyExtractor={(item, index) => {
              return index.toString();
            }}
            renderItem={({ item }) => {
              return (
                <View>
                  <TouchableOpacity
                    onPress={() => {
                      changeSelectedAmount(item.id);
                    }}
                  >
                    <Text
                      style={
                        item.id === selectedAmountId // <-- match id property
                          ? styles.textBoxSelected
                          : styles.textBox
                      }
                    >
                      {item.amount}
                    </Text>
                  </TouchableOpacity>
                </View>
              );
            }}
          />

          <Text>Chose Payment Duration</Text>
          <FlatList
            numColumns={3}
            data={durationArray}
            extraData={selectedDurationId} // <-- prop used to rerender
            keyExtractor={(item, index) => {
              return index.toString();
            }}
            renderItem={({ item }) => {
              return (
                <View>
                  <TouchableOpacity
                    style={
                      item.id === selectedDurationId // <-- match id property
                        ? styles.durationViewPressed
                        : styles.durationView
                    }
                    onPress={() => {
                      changeSelectedDuration(item.id);
                    }}
                  >
                    <View>
                      <Text style={styles.interest}>{item.rate}</Text>
                    </View>
                    <View>
                      <Text style={styles.days}>{item.days}</Text>
                    </View>
                  </TouchableOpacity>
                </View>
              );
            }}
          />
        </View>
      </ScrollView>
    </View>
  );
}

Expo 小吃演示

在此处输入图像描述

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM