【问题标题】:How to update object Array State and screen style on touchable item click in react native如何在可触摸项目上更新对象数组状态和屏幕样式点击反应原生
【发布时间】:2021-05-25 04:35:39
【问题描述】:

我对本机反应有点新,我在反应本机运行时更新对象数组状态和按钮项单击屏幕样式时遇到困难

我尝试使用 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,
  },
});

【问题讨论】:

    标签: javascript reactjs react-native


    【解决方案1】:

    问题

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

    解决方案

    1. 由于您似乎并没有真正更新数组的元素,因此您可以将数组移出组件。它们可以保留const,并且不会在每次渲染时重新声明。
    2. 不必费心尝试更新数组中每个元素的selected 属性,您可以轻松地从selectedDurationIdselectedAmountId 状态值以及渲染时的当前item.id 导出选定状态。
    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 Snack Demo

    【讨论】:

    • 感谢draw,但是在从loan函数中取出对象数组常量后仍然无法正常工作,在用户按下数量或持续时间的TouchableOpacity后,视图在运行时仍然没有改变。请告诉我如何在运行时更新视图的样式以指示新按下的选项
    • @MIikeEps 我明白了。我更新了我的答案并添加了一个正在运行的 Expo Snack 演示。请检查一下。
    • 谢谢十亿。你真的救了我的命
    • 嗨@Drew,请帮助解决以下问题。谢谢stackoverflow.com/questions/69556738/…
    猜你喜欢
    • 2016-03-11
    • 2020-12-12
    • 1970-01-01
    • 1970-01-01
    • 2014-12-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多