Home > front end >  React Native | Changing style of an element in a flatlist using useRef
React Native | Changing style of an element in a flatlist using useRef

Time:10-31

when I click on an element in the flatlist, I just want to change its style. but whichever button I click, only the style of the last element changes. codes below. what do i need to do to fix it?

import { Text, View, FlatList, TouchableOpacity } from 'react-native'
import React, { useRef } from 'react'

const App = () => {

    const ref = useRef()

    const click = () => {
        ref.current.setNativeProps({ style: { backgroundColor: 'blue' } })
    }

    return (
        <View>
            <FlatList
                data={[1, 2, 3, 4, 5]}
                renderItem={({ item }) =>
                    <TouchableOpacity onPress={() => click()} >
                        <View ref={ref} style={{ backgroundColor: '#eee', margin: 5, padding: 20, alignItems: 'center', borderRadius: 10 }}>
                            <Text>{item}</Text>
                        </View>
                    </TouchableOpacity>}
                keyExtractor={(item, index) => index.toString()}
            />

        </View>
    )
}

export default App

CodePudding user response:

You should use this and make the style dynamic, depending on the state value. Maybe you should store your item value in it when you pressed it.

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

const App = () => {

    const ref = useRef()
    const [selectedItem, setSelectedItem] = useState([])

    return (
        <View>
            <FlatList
                data={[1, 2, 3, 4, 5]}
                renderItem={({ item }) =>
                    <TouchableOpacity onPress={() => setSelectedItem([...selectedItem, item])}>
                        <View 
                          ref={ref} 
                          style={[
                            { backgroundColor: '#eee', margin: 5, padding: 20, alignItems: 'center', borderRadius: 10 },
                          selectedItem?.includes(item) && { /* The style you want to apply */ } 
                          ]}
                        >
                            <Text>{item}</Text>
                        </View>
                    </TouchableOpacity>}
                keyExtractor={(item, index) => index.toString()}
            />

        </View>
    )
}

export default App

CodePudding user response:

I would suggest to drop the ref, and just control the background color with state. Also, I would recommend to combine the business logic of the items and their selection into a single state, instead of keeping that information in two separate states. E.g.

function ButtonElement({ item, click }) {
  const backgroundColor = { backgroundColor: item.selected ? "blue" : "#eee" };

  return (
    <TouchableOpacity onPress={() => click(item)}>
      <View
        style={[
          {
            margin: 5,
            padding: 20,
            alignItems: "center",
            borderRadius: 10,
          },
          backgroundColor,
        ]}
      >
        <Text>{item.name}</Text>
      </View>
    </TouchableOpacity>
  );
}

function App() {
  const viewRef = useRef(null);

  const [data, setData] = useState([
    { name: 1, selected: false },
    { name: 2, selected: false },
    { name: 3, selected: false },
    { name: 4, selected: false },
    { name: 5, selected: false },
  ]);

  const click = (selectedItem) => {
    setData((currentData) =>
      currentData.map((item) => {
        if (selectedItem.name === item.name) {
          return { ...item, selected: !item.selected };
        }
        return item;
      })
    );
  };

  return (
    <View>
      <FlatList
        data={data}
        renderItem={({ item }) => <ButtonElement click={click} item={item} />}
        keyExtractor={(item, index) => index.toString()}
      />
    </View>
  );
}

  • Related