How can I get my react native app to automatically refresh data? - postgresql

I am trying to update my react native app to fetch data from the backend every few seconds. Below is my code where I want the data in the transaction history table to update automatically. What is the best way to do this?
import React from 'react';
import PropTypes from 'prop-types';
import { View, StyleSheet, ActivityIndicator, Text, FlatList } from 'react-native';
import TransactionShape from '../../data/model-shapes/Transaction';
import TransactionListItem from '../../components/wallets/TransactionListItem';
import CardStyles from '../../utils/styling/Cards';
import Colors from '../../utils/styling/Colors';
const keyExtractor = ({ id }) => id;
function renderTransactionItem({ item: transaction }) {
return <TransactionListItem transaction={transaction} />;
}
const TransactionHistorySection = ({ transactions, isFetching }) => {
return (
<View style={CardStyles.sectionCard}>
{isFetching ? (
<ActivityIndicator size="large" />
) : (
<View>
<Text style={styles.sectionHeading}>Transaction History</Text>
{transactions.length ? (
<FlatList
data={transactions}
keyExtractor={keyExtractor}
renderItem={renderTransactionItem}
/>
) : (
<Text style={styles.growContainer}>No Transactions</Text>
)}
</View>
)}
</View>
);
};

You coud use a setInterval(function(){ fetch_something }, 3000);
function to run the function to fetch your data on interval you want. then whenever the data change your flatlist will shown the new data

Related

I have React Hook Form With Controller With Yup as validataro The Material UI Select stays red after selecting something and won't go away

I got TextField to work, now the Material UI Select will turn red if no selection is made but stays red after selection is made and won't let form submit. I'm using Yup as validation library.Maybe I keep using wrong Yup type I try String and array but I can't get it to work.
import {
makeStyles,
Box,
Select,
FormControl,
InputLabel,
MenuItem,
Typography,
} from "#material-ui/core";
import * as yup from 'yup';
import { yupResolver } from '#hookform/resolvers'
import { useForm, Controller } from "react-hook-form";
const FormFields = ({ typeOfInquiry, typeOfProviderSupplier, feedbackform }) => {
const schema = yup.object().shape({
typeofInquiry: yup.array().nullable().required(),
});
const { handleSubmit, control, reset, errors } = useForm();
return (
<Controller
style={{ minWidth: 220 }}
name="typeofInquiry"
render ={({ field: { ...field }, fieldState })=>{
console.log(props)
return ( <Select {...field} >
{typeOfInquiry.map((person) => (
<MenuItem key={person.value} value={person.value} >
{person.label}
</MenuItem>
))}
</Select>
)
}}
control={control}
defaultValue=" "
/>
<Typography className={classes.red}>{errors.typeofInquiry?.message}</Typography>
</FormControl>
</form>
);
}
You've to pass the ref to the TextField component.
Here is a working example
👉🏻 https://codesandbox.io/s/exciting-pateu-3n0i9
You should do something similar with Select.
Some examples with MUI: https://codesandbox.io/s/react-hook-form-v7-controller-5h1q5?file=/src/Mui.js

React Hook Form with MUI Toggle Group

I'm trying to use the MUI toggle group with React Hook Form however I can't get the value to post when submitting the form. My toggle group component looks like this:
import FormatAlignCenterIcon from '#material-ui/icons/FormatAlignCenter';
import FormatAlignLeftIcon from '#material-ui/icons/FormatAlignLeft';
import FormatAlignRightIcon from '#material-ui/icons/FormatAlignRight';
import FormatAlignJustifyIcon from '#material-ui/icons/FormatAlignJustify';
import ToggleButton from '#material-ui/lab/ToggleButton';
import ToggleButtonGroup from '#material-ui/lab/ToggleButtonGroup';
import React from 'react';
import {Controller} from "react-hook-form";
export default function TestToggleGroup(props) {
const {control} = props;
const [alignment, setAlignment] = React.useState('left');
const handleAlignment = (event) => {
setAlignment(event[1]);
};
return (
<Controller
name="ToggleTest"
as={
<ToggleButtonGroup
value={alignment}
exclusive
onChange={handleAlignment}
aria-label="text alignment"
>
<ToggleButton value="left" aria-label="left aligned" key="left">
<FormatAlignLeftIcon/>
</ToggleButton>
<ToggleButton value="center" aria-label="centered" key="center">
<FormatAlignCenterIcon/>
</ToggleButton>
<ToggleButton value="right" aria-label="right aligned" key="right">
<FormatAlignRightIcon/>
</ToggleButton>
<ToggleButton value="justify" aria-label="justified" disabled key="justify">
<FormatAlignJustifyIcon/>
</ToggleButton>
</ToggleButtonGroup>
}
value={alignment}
onChange={(e) => {
handleAlignment(e);
}}
valueName={"alignment"}
control={control}
/>
);
}
Not sure exactly what I'm doing wrong but any assistance would be greatly appreciated.
My workaround was using an effect to manually set the value using setValue and then using getValues() inside your handleSubmit function to get the values.
const { control, setValue } = props;
//Effect
React.useEffect(() => {
setAlignment('ToggleTest', alignment);
}, [alignment, setAlignment]);

Material UI filled input for KeyboardDatePicker

I know that with an InputField one is able to pass down the variant="filled" prop to get input box filled. However, is it also possible to pass down a prop with the similar effect using a Material UI date picker (not using the native datepicker from the browser)?
Example of filled input:
I think you are looking for inputVariant={"filled"} prop
import "date-fns";
import React from "react";
import Grid from "#material-ui/core/Grid";
import DateFnsUtils from "#date-io/date-fns";
import {
MuiPickersUtilsProvider,
KeyboardTimePicker,
KeyboardDatePicker
} from "#material-ui/pickers";
export default function MaterialUIPickers() {
// The first commit of Material-UI
const [selectedDate, setSelectedDate] = React.useState(
new Date("2014-08-18T21:11:54")
);
const handleDateChange = date => {
setSelectedDate(date);
};
return (
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<Grid container justify="space-around">
<KeyboardDatePicker
inputVariant={"filled"}
disableToolbar
variant="inline"
format="MM/dd/yyyy"
margin="normal"
id="date-picker-inline"
label="Date picker inline"
value={selectedDate}
onChange={handleDateChange}
KeyboardButtonProps={{
"aria-label": "change date"
}}
/>
</Grid>
</MuiPickersUtilsProvider>
);
}
Working sandbox project link
The #material-ui/pickers has been moved to the #mui/lab.
Checkout the migration guide Here !
Below is a sample code to implement the same
import React from "react";
import TextField from "#mui/material/TextField";
import AdapterDateFns from "#mui/lab/AdapterDateFns";
import LocalizationProvider from "#mui/lab/LocalizationProvider";
import DatePicker from "#mui/lab/DatePicker";
export default function filledDatePicker() {
const [selectedDate, setSelectedDate] = React.useState(new Date());
const handleDateChange = date => {
setSelectedDate(date);
};
return (
<LocalizationProvider dateAdapter={AdapterDateFns}>
<DatePicker
value={selectedDate}
onChange={handleDateChange}
renderInput={(props) => (
<TextField {...props} variant="filled" label="Select Date" />
)}
/>
</LocalizationProvider>
);
}

Use 'navigation' and 'route' inside header present in class - React-navigation v5

I'm stuck as I want to switch to the V5 version of react-navigation.
With v4, I used to pass my params and use them with :
Set :
this.props.navigation.navigate('MyDestination', {myParam: 'value'})
Get :
this.props.navigation.getParam('myParam')
With v5, some things changed and I now can't use the this.props.navigation since it's not seemed to be known by the app.
My code is splitted so I have my App.js that only refer to the Navigation class :
import React from 'react';
import { StyleSheet, Text, View } from 'react-native'
import Navigation from './navigation/Navigation'
export default function App() {
return (
<Navigation/>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Then my Navigation file contains all the navigation mechanism (I did not added my TabBar yet, since I want to fix the base navigation first) :
import { NavigationContainer } from '#react-navigation/native'
import { createStackNavigator } from '#react-navigation/stack'
import { createBottomTabNavigator } from 'react-navigation-tabs'
import { StyleSheet, Image } from 'react-native'
import React from 'react'
import Home from '../components/Home'
import LendList from '../components/LendList'
import AddMoney from '../components/AddMoney'
import AddStuff from '../components/AddStuff'
import Settings from '../components/Settings'
import Test from '../components/Test'
function HomeScreen() {
return(
<Home/>
)
}
function LendListScreen() {
return(
<LendList/>
)
}
const Stack = createStackNavigator()
function App() {
return(
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home"
component={Home}
options={{ title: "Home Page"}}
/>
<Stack.Screen name="LendList"
component={LendList}
options={{ title: 'Liste' }}
/>
<Stack.Screen name="AddMoney"
component={AddMoney}
options={{ title: "Ajout Money"}}
/>
<Stack.Screen name="AddStuff"
component={AddStuff}
options={{ title: "Ajout Stuff"}}
/>
<Stack.Screen name="Settings"
component={Settings}
options={{ title: "Settings"}}
/>
<Stack.Screen name="Test"
component={Test}
options={{ title: "Test"}}
/>
</Stack.Navigator>
</NavigationContainer>
)
}
export default App
And then come each of my pages (coded with classes), and here is one example, Home.js (I removed all the Style part to shorten the code displayed here) :
import React from 'react'
import { StyleSheet, Text, Image, View, Button, TouchableOpacity } from 'react-native'
import Moment from 'react-moment'
import { CommonActions } from '#react-navigation/native'
import { useNavigation } from '#react-navigation/native'
class Home extends React.Component {
static navigationOptions = () => {
return {
headerRight: () => <TouchableOpacity style={styles.settings_touchable_headerrightbutton}
onPress={() => this.goToSettings()}>
<Image style={styles.settings_image}
source={require('../assets/ic_settings.png')} />
</TouchableOpacity>
}
}
constructor(props) {
super(props)
this._goToSettings = this._goToSettings.bind(this)
}
_updateNavigationParams() {
navigation.setParams({
goToSettings: this._goToSettings
})
}
componentDidMount(){
console.log("navigation")
this._updateNavigationParams()
}
_checkMoneyDetails(navigation){
navigation.navigate('LendList', {type: 'Money'})
}
_checkStuffDetails(navigation){
navigation.navigate('LendList', {type: 'Stuff'})
}
_checkPeopleDetails(navigation){
navigation.navigate('LendList', {type: 'People'})
}
_goToSettings = () => {
navigation.navigate('Settings')
}
render(){
const date = new Date();
const { navigation } = this.props;
return(
<View style={styles.main_container}>
<View style={styles.header_view}>
<Text style={styles.header_text}>GiViToMe</Text>
<Text style={styles.header_text}>Nous sommes le :{' '}
{/* TODO: Penser à gérer ensuite les formats de date étrangers */}
<Moment element={Text} format="DD/MM/YYYY" date={date}/>
</Text>
</View>
<View style={styles.lend_view}>
<Text style={styles.title_lend_text}>Vos prêts :</Text>
<View style={styles.money_stuff_view}>
<View style={styles.money_view}>
<View style={styles.money_data_view}>
<Image source={require('../assets/ic_money.png')} style={styles.home_img} />
<Text>XXX $</Text>
</View>
<Button title='Money' onPress={() => {this._checkMoneyDetails(navigation)}}/>
</View>
<View style={styles.stuff_view}>
<View style={styles.stuff_data_view}>
<Image source={require('../assets/ic_box.png')} style={styles.home_img} />
<Text>XXX objets</Text>
</View>
<Button title='Stuff' onPress={() => {this._checkStuffDetails(navigation)}}/>
</View>
</View>
<View style={styles.people_view}>
<View style={styles.people_data_view}>
<Image source={require('../assets/ic_people.png')} style={styles.home_img} />
<Text>XXX people</Text>
</View>
<Button title='People' onPress={() => {this._checkPeopleDetails(navigation)}}/>
</View>
</View>
<View style={styles.footer_view}>
<Text style={styles.text_footer_view}>a.vescera inc.</Text>
</View>
</View>
)
}
}
export default Home
My problem is that, per the online documentation, I saw that to use "navigation" or "route" within a class, I should use the const navigation = { this.props } after the render() function.
This problem is that, to use one specific function within the header, I have to bind it after the componentDidMount() function, but the value present under render() is not yet known.
How could I solve this ? (sure that in the given example, having all the code in the navigation part allow to use navigation and route easily but you understand that I have to split my code.
Thanks.
Ok, so each time the same, I try many days solving my problem, and when I finally decide to post on stack, I find a solution :).
So, if there's some performance issue or other you may see by looking at my code, do not hesitate to correct me. I just found that this solution solved my problem.
So within my Navigation.js file, I just passed the navigation and route objects to make them usable thanks to the props into my classes, like this :
function App() {
return(
<NavigationContainer>
<Stack.Navigator initialRouteName="Home">
<Stack.Screen name="Home"
component={Home}
options={({route, navigation}) => (
{headerTitle: 'Home Page',
route: {route},
navigation: {navigation}}
)}
/>
</Stack.Navigator>
</NavigatorContainer>
)}
then within my classes I just call to this.props.navigation or this.props.route and gather form these objects what I need.
Other thing is that, for those who would use this code to build something similar, I also had to change the way I display the header button.
I do not use the static navigationOptions = () => {} anymore. I just add directly the navigation.setOptions piece of code within the ComponentDidMount function like this:
navigation.setOptions({
headerRight: () => <TouchableOpacity style={styles.settings_touchable_headerrightbutton}
onPress={() => route.params.goToSettings()}>
<Image style={styles.settings_image}
source={require('../assets/ic_settings.png')} />
</TouchableOpacity>
})
I have to do it this way since I'm using a function declared in my class, so I have to bind it in the constructor like this this._goToSettings = this._goToSettings.bind(this) and then add it to the navigation.setParams function.
When navigation.setOptions code is written inside componentDidMount add this.props before navigation and route keyword. Below is the code snippet that worked for me.
this.props.navigation.setOptions({
headerRight: () => <TouchableOpacity style={styles.settings_touchable_headerrightbutton}
onPress={() => this.props.route.params.goToSettings()}>
<Image style={styles.settings_image}
source={require('../assets/ic_settings.png')} />
</TouchableOpacity>
})

How to onRowClick redirected to another page with mui-datatables npm package?

I have a react app that uses package mui-datatables. I want to be redirected to "/edit-form" onRowClick, but it didn't work (nothing happens, no errors either).
import React, { Component } from "react";
import { Link as RouterLink } from "react-router-dom";
import Link from "#material-ui/core/Link";
import MUIDataTable from "mui-datatables";
class DataTable extends Component {
state={...}
redirectToForm = props => <RouterLink to="/edit-form" {...props}/>
render() {
const options = {
onRowClick: rowData => this.redirectToForm(rowData)
};
return (
<Link
color="secondary"
className={classes.button}
component={this.goToDetailedTable}
>
Detail
</Link>
<MUIDataTable
title={title}
columns={value.state.columnName}
data={value.state.rowData}
options={options}
/>
)
}
When I console.log(rowData), it did print out the row data:
const options = {
onRowClick: rowData => console.log(rowData)
};
Instead of using <Link/> try calling history from the history package and then just history.push('edit/form').