I'm curious if there is a method in React Native to dynamically alter the color of a button depending on a boolean value retrieved from a database source

Hey there, I'm completely new to React-Native and just started playing around with it. I encountered an issue where I needed a button to change its color dynamically between "green" and "red" based on a boolean value from a database.

Currently, I am using Google's "Firebase" as my main database.
Here is the initial code I have been working on:

import {StatusBar} from 'expo-status-bar';
import React, {Component} from 'react';
import {StyleSheet, Text, View, Pressable, TouchableOpacity} from 'react-native';

import {initializeApp} from 'firebase/app';
import {getDatabase, ref, onValue, set} from 'firebase/database';
import {color} from 'react-native-reanimated';

const firebaseConfig = {};
initializeApp(firebaseConfig);

export default class App extends Component {
  constructor() {
    super();
    this.state = {
      l1: this.readVals('l1/'),
    };
  }

  readVals(path) {
    const db = getDatabase();
    const reference = ref(db, path);
    onValue(reference, (snapshot) => {
      const value = snapshot.val().obj;
      return value;
    });
  
  }

  setVals(path) {
      const db = getDatabase();
      const reference = ref(db, path);
      const val = this.state.l1;
      set(reference, {
        obj: !val
      });
      this.state.l1 = !val;
    }
  render() {
    return (
      <View style={styles.container}>
        <Pressable
          style={({pressed}) => [
            {
              backgroundColor: this.state.l1 ? '#FF0000' : '#00FF00',
            },
            styles.button,
          ]} onPress={() => {this.setVals('l1/')}}>
          <Text style={styles.buttonText}>Button</Text>
        </Pressable>

         <StatusBar style="auto" />
       </View>
     );
   }
}

const styles = StyleSheet.create({
   container: {
     flex: 1,
     backgroundColor: '#FF0000',
     alignItems: 'center',
     justifyContent: 'center',
   },
   getButton: {
     borderWidth: 1,
     borderColor: 'rgba(0,0,0,0.5)',
     alignItems: 'center',
     justifyContent: 'center',
     alignSelf: 'center',
     borderWidth: 2,
     borderRadius: 7,
     marginTop: 20,
     width: 100,
     height: 50,
     backgroundColor: '#00FF00',
   },

   button: {
     flex: 0.15,
     borderWidth: 1,
     borderColor: 'rgba(0,0,0,0.25)',
     alignItems: 'center',
     justifyContent: 'center',
     alignSelf: 'center',
     borderWidth: 2,
     borderRadius: 10,
     marginTop: 20,
     width: 200,
     height: 100,
     // backgroundColor: '#E84C3D'
   },
   buttonText: {
     fontWeight: 'bold',
     fontSize: 20,
   },
 });

When I click the button, the color changes correctly. Is there a way to make the color change based on the database value?

For instance, I would like the button to be initially 'green' if the value at 'l1/' location in "firebase" is true, and 'red' if the value is false.

Is this feasible?
Any guidance on implementing this would be greatly appreciated.
Thank you.

P.S. Please keep in mind that I am very new to React-Native(Sorry).

Answer №1

To refresh the screen using reRender, you need to utilize the state and have your Screen render again when it's altered. It appears that is what you've done, but there is another approach you can try. Initially, retrieve your data in the componentDidMount method like this:

  componentDidMount() {
    console.log("componentDidMount");
     this.setState({  l1: this.readVals('l1/') });
  }

If l1 is changed, it should work for you.

Alternatively, if you wish for the UI to update immediately after a database change, you have two options. The first is to employ socket programming such as signalR component. For more information, refer to this link

The second option is to use firebaseMessaging with Firebase where JSON data is sent via notification when a database change occurs. Find out more at this link

Answer №2

When implementing a class-based component, you can utilize a firebase function within the componentWillMount lifecycle method to retrieve and store color data in your component's state.

The componentWillMount method executes before rendering, allowing you to set the state with the retrieved data and dynamically change the button's color based on that state.

Give it a Try!

import {StatusBar} from 'expo-status-bar';
import React, {Component} from 'react';
import {StyleSheet, Text, View, Pressable, TouchableOpacity} from 'react-native';

import {initializeApp} from 'firebase/app';
import {getDatabase, ref, onValue, set} from 'firebase/database';
import {color} from 'react-native-reanimated';

const firebaseConfig = {};
initializeApp(firebaseConfig);

export default class App extends Component {
  constructor() {
    super();
    this.state = {
      l1: this.readValues('l1/'),
    };
  }

  componentWillMount() {
    const value = this.readValues('l1/');
    this.setState({l1: value});
  }

  readValues(path) {
    const db = getDatabase();
    const reference = ref(db, path);
    onValue(reference, (snapshot) => {
      const value = snapshot.val().obj;
      return value;
    });
  }
  render() {
    return (
      <View style={styles.container}>
        <Pressable
          style={({pressed}) => [
            {
              backgroundColor: this.state.l1 ? '#FF0000' : '#00FF00',
            },
            styles.button,
          ]}>
          <Text style={styles.buttonText}>Button</Text>
        </Pressable>

        <StatusBar style="auto" />
      </View>
    );
  }
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#FF0000',
    alignItems: 'center',
    justifyContent: 'center',
  },
  getButton: {
    borderWidth: 1,
    borderColor: 'rgba(0,0,0,0.5)',
    alignItems: 'center',
    justifyContent: 'center',
    alignSelf: 'center',
    borderWidth: 2,
    borderRadius: 7,
    marginTop: 20,
    width: 100,
    height: 50,
    backgroundColor: '#00FF00',
  },

  button: {
    flex: 0.15,
    borderWidth: 1,
    borderColor: 'rgba(0,0,0,0.25)',
    alignItems: 'center',
    justifyContent: 'center',
    alignSelf: 'center',
    borderWidth: 2,
    borderRadius: 10,
    marginTop: 20,
    width: 200,
    height: 100,
    // backgroundColor: '#E84C3D'
  },
  buttonText: {
    fontWeight: 'bold',
    fontSize: 20,
  },
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The compatibility between Typescript methods and event handlers is lacking

Consider this basic TypeScript script class foo { v: number = 1; public bar() { console.log(this.v); } } var a = new foo(); var b = new foo(); document.getElementById('test').addEventListener("click", a.bar); document.getE ...

conditionally trigger one observable in rxjs before the other

I am in need of assistance or guidance regarding a challenge I am facing with rxjs that I cannot seem to resolve. In essence, my goal is to trigger an observable and complete it before the original one is triggered. Scenario: I am currently working on a ...

Creating synthetic data using the Faker library

I'm currently developing a script that utilizes the faker and JSON-Schema-Faker libraries to generate test data. I am specifically interested in examples involving "schema inheritance" and optional fields. For instance, I have a 'user' obje ...

Is there a way for me to insert a variable into the src attribute of my img tag like this: `<img alt="Avatar" src=`https://graph.facebook.com/${snAvatarSnuid}/picture`>`

I need assistance with passing a variable called snAvatarSnuid within the img src tag, specifically after facebook.com/ and before /picture as shown below: <img alt="Avatar" src=`https://graph.facebook.com/${snAvatarSnuid}/picture`> Note: 1) The ht ...

Downloading Files from Mongodb Using GridFS

I am working on an application that enables users to upload and download various files. Currently, I am facing a challenge where I am able to retrieve the file from my MongoDB database and download it locally on my machine, but I am encountering difficulti ...

How can I pass a string value from C++ to JavaScript in a Windows environment using Visual Studio 2008?

In my current project, I have successfully implemented an IDL for passing a string value from JavaScript to C++. The JavaScript code effectively passes a string value to the C++/COM object. [id(1), helpstring("method DoSomething")] HRESULT DoSomething([in ...

Generate a JSON (Jquery) structured table matrix outlining various roles and corresponding permissions such as read, write, delete, and write special

I would like to create a table matrix that displays roles and permissions (read, write, delete, write special) using jQuery with JSON data. The table should contain checkboxes for each permission type, and the checkboxes for read, write, delete, and write ...

Windows npm configuration settings

After receiving helpful answers to my previous question about using a named parameter in an npm run script, I encountered a new problem. It seems that the $npm_config_variable doesn't function correctly on Windows OS. I am in search of a solution that ...

Assist me in minimizing redundant code in a basic jQuery function

I successfully created a carousel using the jQuery cycle plugin with 4 links that correspond to different slides. Currently, I have separate blocks of code for each link, but I'm looking to optimize by creating a single function. $('#features-sl ...

What is causing the 'Invalid Hook Call' error to appear in React?

I have recently started learning React and I am currently working on converting a functional component into a class component. However, I encountered an error message that says: Error: Invalid hook call. Hooks can only be called inside of the body of a fu ...

What is the best way to display the unique $index for an array retrieved from Firebase?

I am currently facing an issue. Everything is progressing smoothly. I am using ngRepeat to display lists that are Arrays from Firebase using the $asArray() function. In addition, I am applying a "reverse" filter so that new items appear at the top. Now ...

Ways to widen the header to fit the entire page?

I'm having trouble stretching my header to fill the entire page. I've tried using margin-left and right, but it's not working as expected. My Header CSS: background: green; height: 70px; width: 100%; display: flex; just ...

Ways to create space around Navbar MUI for a more balanced design

Currently, I am working on designing a navigation bar using MUI. My goal is to create a navbar with some space on both sides similar to the one seen on https://i.sstatic.net/lPXyC.png If you take a look at Stackoverflow's navbar, you will notice that ...

Tips for updating form values with changing form control names

Here is an example of a form I created: public profileSettingsGroup = new FormGroup({ firstName: new FormControl('Jonathon', Validators.required) }) I also have a method that attempts to set control values in the form: setControlValue(contro ...

Safari on iOS9 is inaccurately calculating the total sum

My code involves calculating the sum of key/value pairs in a hash within a loop. I have noticed that there is a discrepancy in how the sum is calculated on ios9 Safari compared to other platforms. While I can address this issue for this specific scenario, ...

Vue: Child component not rendering string prop

Hey there, I'm currently exploring the ins and outs of Vue and diving into its one-way data bind model, component registration, and passing props. Within my index.js file, I've set up my parent component to render a single child component for no ...

Storing a MySQL query result in a global array in a Node.js environment

Just diving into the world of Node.js and Express, I'm trying to wrap my head around asynchronous functions and global variables. Specifically, I'm working on connecting to a MySQL database, fetching query results, and displaying them on a test.h ...

Get your hands on the base64 image by triggering the save as popup and downloading

I am facing a challenge with downloading a base64 image onto the user's machine. So far, I have attempted the following steps: var url = base64Image.replace(/^data:image\/[^;]+/, 'data:application/octet-stream'); window.open(url); an ...

Verifying Angular (2+?) Compatibility: Opening and Closing Material mat-menu on Hover [GUIDE]

After extensive research, I tried various methods to hover a material menu to display its options. However, the solutions I came across were either too complicated or ineffective. Therefore, I decided to develop my own solution by combining elements of e ...

Mastering div manipulation with jQuery: A step-by-step guide

I have three divs with the classes "col-md-2," "col-md-8," and "col-md-2." What I want is that when a button in the "col-md-8" div is clicked, both of the other divs should be hidden and the "col-md-8" div should expand to occupy the full width of "col-md ...