I want to render a specific static object in react native - react-native

I try to render a specific object inside a component (static object) in react native,after i get it with http request from axios API .The (node)server works fine but whenever i try to render it on the screen nothing shows.
Also when i console.log the object its correct(on client side too) but still nothing on simulator screen.
I dont know if i do something wrong or i need hooks for that(im new in react native so excuse me if i open again some same question) .
The code is below :
Client
import React, { Component,
useEffect,
useState } from 'react';
import {
StyleSheet,
Text,
View ,
} from 'react-native';
import axios from 'axios';
var res;
export default function App() {
axios.get('http://x.x.x.x:x/rec')
.then
(function (response){
console.log(response.data);
res = response.data;
})
return (
<View style = {styles.container}>
<Text>This car is a : {res}</Text>
</View>
)};
const styles = StyleSheet.create({
container: {
flex: 1 ,
marginTop:100,
},
});
Server
const app = require('express')();
const { json } = require('body-parser');
const car = {
type: "Fiat",
model : "500"
};
const myCar = JSON.stringify(car);
app.get("/rec",(req,res) => {
res.send(myCar);
console.log("Took Car");
})
app.get("/",(req,res) => {
res.set('Content-Type', 'text/plain');
res.send("You have done it ");
console.log("Took /");
})
var listener = app.listen(8888,()=>{
console.log(listener.address().port);
});

Better to use hook for it
import React, { Component, useEffect, useState } from 'react';
import { StyleSheet, Text, View } from 'react-native';
import axios from 'axios';
export default function App() {
const [label, setLabel] = useState('')
axios.get('http://x.x.x.x:x/rec')
.then((response) => {
const data = response.data
const resultLabel = typeof data === 'string' ? data :
`${data.type} ${data.model}`
setLabel(`This car is a : ${resultLabel}`)
})
return (
<View style = {styles.container}>
<Text>{label}</Text>
</View>
)};
const styles = StyleSheet.create({
container: {
flex: 1,
marginTop:100,
},
});

Related

RTK query function is undefined in react native

I'm using RTK query to fetch data from the endpoint, setup the folder structure like this
src (root)
features/api/apiSlice.js
screens/ChatScreen.js
I have setup apiSlice.js like this
import {createApi, fetchBaseQuery} from '#reduxjs/toolkit/query/react';
export const apiSlice = createApi({
reducerPath: 'api',
baseQuery: fetchBaseQuery({baseUrl: 'https://api.covid19api.com'}),
endpoints: builder => ({
getEmojiPoints: builder.query({
query: () => '/countries',
}),
}),
});
export const {useGetEmojiPoints} = apiSlice;
then imported the useGetEmojiPoints hook in functional component like this
import {useGetEmojiPoints} from '../features/api/apiSlice';
const {
data: emojiPoints,
isLoading,
isSuccess,
isError,
error,
} = useGetEmojiPoints(); // getting this undefined (not a function)
Setup App.js like this
import React from 'react';
import {
SafeAreaView,
ScrollView,
StatusBar,
useColorScheme,
Text,
StyleSheet,
} from 'react-native';
import ChartScreen from './src/screens/ChartScreen';
import {ApiProvider} from '#reduxjs/toolkit/query/react';
import {apiSlice} from './src/features/api/apiSlice';
const AppWrapper = () => {
return (
<ApiProvider api={apiSlice}>
<App />
</ApiProvider>
);
};
const App = () => {
const isDarkMode = useColorScheme() === 'dark';
return (
<SafeAreaView style={styles.container}>
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
<ScrollView>
<ChartScreen />
</ScrollView>
</SafeAreaView>
);
};
const styles = StyleSheet.create({
container: {flex: 1, backgroundColor: '#fff'},
});
export default AppWrapper;
Whats wrong why its giving me undefined for query hook?
It's useGetEmojiPointsQuery, not useGetEmojiPoints.

How to use redux component in App.js React Native?

I'm doing a simple counter app. It has one label, and a button that you can increment by + 1 (each time it's pushed).
Using redux, I want to use the count that I store (in my Redux Store) in App.js file. However, I'm getting an error:
Error: could not find react-redux context value; please ensure the component is wrapped in a Provider
Using the useSelector works in other files, just not App.js. Is there a work around?
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Dogs from './components/Dogs';
import { Provider, useSelector } from 'react-redux';
import store from './redux/configureStore'
export default function App() {
const count = useSelector((state) => state.counter.count);
{/*useSelector does not work in this file!*/}
return (
<Provider store={store}>
<View style={styles.container}>
<Text>{`ha ${count}`}</Text>
<Dogs />
</View>
</Provider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Counter.js
import React, { useState, useEffect } from "react";
import { View, Text, StyleSheet, Button} from "react-native";
import { useDispatch, useSelector } from "react-redux";
import { increment } from '../redux/ducks/counter'
const Counter = () => {
const count = useSelector((state) => state.counter.count);
{/*useSelector works in this file!*/}
const dispatch = useDispatch();
const handleIncrement = () => {
dispatch(increment())
};
return (
<div>
{/* <Text>{` COunt: ${count}`}</Text> */}
<Button onPress={handleIncrement}>Increment</Button>
</div>
);
}
const styles = StyleSheet.create({})
export default Counter;
redux/configureStore.js
import { combineReducers, createStore } from 'redux';
import counterReducer from './ducks/counter';
const reducer = combineReducers({
counter: counterReducer
});
const store = createStore(reducer);
export default store;
redux/ducks/counter.js
const INCREMENT = 'increment';
export const increment = () => ({
type: INCREMENT
})
const initialState = {
count: 0
};
export default ( state = initialState, action) => {
switch(action.type) {
case INCREMENT:
return{...state, count: state.count + 1}
default:
return state;
}
};
As error saying, you are using useSelector out side of provider. In your app.js you are using useSelector before the app renders, so it is not able to find store. So, create a component for functionality which you want to use in app.js like this :
Create a file, call it anything like CountView.js, in CountView.js use your redux login :
CountView.js
import React from 'react';
import { Text } from 'react-native';
import { useSelector } from 'react-redux';
const CountView = () => {
const count = useSelector((state) => state.counter.count);
return (
<Text>{`ha ${count}`}</Text>
)
}
export default CountView;
Now, In your app.js use this component :
import React from 'react';
import { StyleSheet, Text, View } from 'react-native';
import Dogs from './components/Dogs';
import { Provider } from 'react-redux';
import store from './redux/configureStore'
import CountView from '../components/CountView'; // import CountView component
export default function App() {
return (
<Provider store={store}>
<View style={styles.container}>
{/* Use component here */}
<CountView />
<Dogs />
</View>
</Provider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
});
Keep other things as it is, and now your functionality will works.
useSelector will work only if you wrap it inside Provider. you can create a wrapper file for App.
const AppWrapper = () => {
return (
<Provider store={store}> // Set context
<App /> // Now App has access to context
</Provider>
)
}
In App.js
const App = () => {
const count = useSelector((state) => state.counter.count); // will Work!
}
Unlike a regular React application, an expo React-Native application is not wrapped using an index.js file. Therefore when we wrap the provider in app.js for a React-Native app, we wrap it in index.js for React application. So the hooks like useSelector or useDispatch run before the provider is initialized. So, I would suggest not using any hooks in the app component, instead, we can create other components in the app.js and use the hooks in a separate component like in the code I have used below.
const Root = () => {
const [appIsReady, setAppIsReady] = useState(false);
const dispatch = useDispatch();
const fetchToken = async () => {
const token = await AsyncStorage.getItem("token");
console.log("Stored Token: ", token);
if (token) {
dispatch(setAuthLogin({ isAuthenticated: true, token }));
}
};
const LoadFonts = async () => {
await useFonts();
};
useEffect(() => {
async function prepare() {
try {
await SplashScreen.preventAutoHideAsync();
await LoadFonts();
await fetchToken();
} catch (e) {
console.warn(e);
} finally {
setAppIsReady(true);
}
}
prepare();
}, []);
const onLayoutRootView = useCallback(async () => {
if (appIsReady) {
await SplashScreen.hideAsync();
}
}, [appIsReady]);
if (!appIsReady) {
return null;
}
return (
<NavigationContainer onReady={onLayoutRootView}>
<MainNavigation />
</NavigationContainer>
);
};
export default function App() {
return (
<>
<Provider store={store}>
<ExpoStatusBar style="auto" />
<Root />
</Provider>
</>
);
}

Check the render method of `InstanceImage` while testing using testing-library/react-native

I am trying to test a functional component with Redux using testing-library/react-native.
//InstanceImage.component.js
export default InstanceImage = (props) => {
// <props init, code reduced >
const { deviceId, instanceId } = DeviceUtils.parseDeviceInstanceId(deviceInstanceId)
const deviceMap = useSelector(state => {
return CommonUtils.returnDefaultOnUndefined((state) => {
return state.deviceReducer.deviceMap
}, state, {})
})
const device = deviceMap[deviceId]
const instanceDetail = device.reported.instances[instanceId]
if (device.desired.instances[instanceId] !== undefined) {
return (
<View
height={height}
width={width}
>
<ActivityIndicator
testID={testID}
size={loadingIconSize}
color={fill}
/>
</View>
)
}
const CardImage = ImageUtils[instanceDetail.instanceImage] === undefined ? ImageUtils.custom : ImageUtils[instanceDetail.instanceImage]
return (
<CardImage
testID={testID}
height={height}
width={width}
fill={fill}
style={style}
/>
)
}
And the test file is
//InstanceImage.component.test.js
import React from 'react'
import { StyleSheet } from 'react-native';
import { color } from '../../../../src/utils/Color.utils';
import ConstantsUtils from '../../../../src/utils/Constants.utils';
import { default as Helper } from '../../../helpers/redux/device/UpdateDeviceInstanceIfLatestHelper';
import InstanceImage from '../../../../src/components/Switches/InstanceImage.component';
import { Provider } from 'react-redux';
import { render } from '#testing-library/react-native';
import configureMockStore from "redux-mock-store";
import TestConstants from '../../../../e2e/TestConstants';
const mockStore = configureMockStore();
const store = mockStore({
deviceReducer: {
deviceMap: Helper.getDeviceMap()
}
});
const currentState = ConstantsUtils.constant.OFF
const styles = StyleSheet.create({
// styles init
})
const props = {
//props init
}
describe('Render InstanceImage', () => {
it('InstanceImage renders correctly with values from props and Redux', () => {
const rendered = render(<Provider store={store}>
<InstanceImage {...props}/>
</Provider>)
const testComponent = rendered.getByTestId(TestConstants.icons.INSTANCE_IMAGE)
});
})
And when I run the test file it gives the following error
Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object.
Check the render method of `InstanceImage`.
The component runs correctly when the app is run and there aren't any crashes. Still, this error occurs while performing tests.I am new to creating test cases for react native app so not able to debug this issue.
Found the error, the CardImage returns a custom svg image which was causing the issue. I used the jest-svg-transformer and it solved the issue.
Reference: https://stackoverflow.com/a/63042067/4795837

React useEffect raises 'create is not a function' error

I have the following React Native module:
import React, {useContext, useEffect} from 'react';
import {Image, StyleSheet} from 'react-native';
import AsyncStorage from '#react-native-community/async-storage';
import AuthContext from '../context/auth/authContext';
const Intro = () => {
const getLocalUser = async () => {
try {
const value = await AsyncStorage.getItem('user');
return value;
} catch (error) {
console.log(error);
}
};
const localUser = getLocalUser();
const {setUser} = useContext(AuthContext);
useEffect(() => {
setUser({localUser});
}, []);
return (
<Image
style={styles.image}
source={require('../static/logo_intro.png')}
/>
);
}
const styles = StyleSheet.create({
image: {
width: 430,
resizeMode: 'center',
paddingTop: 500
}
})
export default Intro;
That raises the following error: [Tue Sep 08 2020 15:00:47.220] ERROR TypeError: create is not a function. (In 'create()', 'create' is undefined).
I checked this question, but I am already doing it.
It might be that you have to use useState instead of useEffect.
See https://github.com/facebook/react/issues/15194 for a lead into why this error is shown this way.

can react-native-root-siblings work with react-redux

in a handleClick function, update the rootSiblings like this,
handleClick() { this.progressBar.update( <ProgressBar /> ); }
and in ProgressBar component,
import React, { PropTypes } from 'react';
import { connect } from 'react-redux';
import { View } from 'react-native';
const getFinishedWidth = progress => ({ width: progress * totalWidth });
const getUnfinishedWidth = progress => ({ width: (1 - progress) * totalWidth });
function CustomerReassignProgressBar(props) {
const { progress } = props;
return (
<View style={styles.bar}>
<View style={getFinishedWidth(progress)} />
<View style={getUnfinishedWidth(progress)} />
</View> );
}
CustomerReassignProgressBar.propTypes = { progress: PropTypes.number, };
const mapStateToProps = state => ({ progress: state.batchReassignProgress, });
export default connect(mapStateToProps)(ProgressBar);
then, when calling handleClick(), the app crushed, the error is, 'Could not find "store" in either the context or props of "Connect(ProgressBar)". Either wrap the root component in a , or explicitly pass "store" as a prop to "Connect(ProgressBar)".'
if I don't use connect in component, it works well. So, I guess, maybe rootSiblings can not work with react-redux. But does anyone knows this problem?
Upgrade to react-native-root-siblings#4.x
Then
import { setSiblingWrapper } from 'react-native-root-siblings';
import { Provider } from 'react-redux';
const store = xxx;// get your redux store here
// call this before using any root-siblings related code
setSiblingWrapper(sibling => (
<Provider store={store}>{sibling}</Provider>
));