0

I'm trying to get the dynamic rating and render my dynamic svg component accordingly, but after there occurs a change in state after the user select the star, the component is not being re-rendered, enter image description here

After the user selects the star from the component, the data from the state is changing but the component is not being re-rendered even there is a change in the state.

enter image description here this is the console logged value of the changed state.

this is the code of the component where logic is present

import React, {useEffect, useState} from 'react';
import {View, Text, StyleSheet, TouchableOpacity} from 'react-native';

import DirectionalShadow from './directionalShadow';

import Colors from '../res/colors';
import Images from '../res/images';
import SVGImages from '../res/images/dynamicSVG';

const RatingCard = props => {
  const [starData, setStarData] = useState([true, false, false, false, false]);

  const changeStar = data => {
    setStarData(data);
    console.log('Data logged');
    console.log(starData);
  };

  return (
    <View>
      <DirectionalShadow
        paddingBottom={1}
        shadowColor={Colors.textInputShadow}
        style={{
          borderRadius: 6,
          marginHorizontal: 16,
          marginTop: 10,
        }}>
        <View style={styles.cards}>
          <View>
            <View
              style={{
                flexDirection: 'row',
                alignItems: 'center',
                marginTop: 13,
                marginLeft: 19,
                justifyContent: 'space-between',
              }}>
              <Text
                style={{
                  color: Colors.grayLight,
                  fontSize: 14,
                  fontFamily: 'Ubuntu-Regular',
                }}>
                {props.text}
              </Text>
              <View style={{flexDirection: 'row', alignItems: 'center'}}>
                {starData.map((item, index) => (
                  <TouchableOpacity
                    key={index}
                    activeOpacity={0.75}
                    onPress={() => {
                      var temp = starData;
                      for (var i = 0; i < starData.length; i++) {
                        if (i <= index) {
                          temp.splice(i, 1, true);
                        } else {
                          temp.splice(i, 1, false);
                        }
                      }
                      changeStar(temp);
                    }}
                    style={{marginHorizontal: 5}}>
                    {item ? (
                      <SVGImages.Star color={Colors.green} />
                    ) : (
                      <SVGImages.Star />
                    )}
                  </TouchableOpacity>
                ))}
              </View>
            </View>
          </View>
        </View>
      </DirectionalShadow>
    </View>
  );
};

const styles = StyleSheet.create({
  cards: {
    height: 50,
    paddingRight: 20,
    borderRadius: 6,
    backgroundColor: Colors.textInputBackground,
    shadowColor: '#000',
    shadowOffset: {
      width: 0,
      height: 4,
    },
    shadowOpacity: 0.3,
    shadowRadius: 4.65,
    elevation: 8,
  },
});
export default RatingCard;

  • 1
    looks like it is rendering, otherwise you wouldn't get console.log. the issue is it does not reflect on the ui. make sure you are using the state. – Yilmaz Aug 13 '21 at 06:34
  • I'm using useState hook to render the component like this `{starData.map((item, index) => ( { var temp = starData;` – Hardik poudel Aug 13 '21 at 06:38

1 Answers1

1

You need to create a copy of your array const temp = [...starData];, if you just manipulate the array the hook won‘t recognize that something changed.

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


const ToggleSquareArray = () => {
  const [squareData, setSquareData ] = useState([true, false, false, false, false]);

  const changeSquare = data => {
    setSquareData(data);
    console.log('Data logged');
    console.log(squareData);
  };

  return (
    <View>
          <View>
            <View
              style={{
                flexDirection: 'row',
                alignItems: 'center',
                marginTop: 13,
                marginLeft: 19,
                justifyContent: 'space-between',
              }}>
              <View style={{flexDirection: 'row', alignItems: 'center'}}>
                {squareData.map((item, index) => (
                  <TouchableOpacity
                    key={index}
                    activeOpacity={0.75}
                    onPress={() => {
                      const temp = [...squareData]; // Create a copy of the array you wanna manipulate should do the trick
                      temp.splice(index, 1, !temp[index]);
                      console.log(temp);

                      changeSquare(temp);
                    }}
                    style={{marginHorizontal: 5}}>
                    {item ? (
                      <View style={{height: 50, width: 50, backgroundColor: '#ff0000'}} />
                    ) : (
                      <View style={{height: 50, width: 50, backgroundColor: '#ff00ff'}} />
                    )}
                  </TouchableOpacity>
                ))}
              </View>
            </View>
          </View>
    </View>
  );
};

export default ToggleSquareArray;
Michael Bahl
  • 2,941
  • 1
  • 13
  • 16