skip to Main Content

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

2

Answers


  1. 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
    
    Login or Signup to reply.
  2. 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>
      );
    }
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search