How to change react native app layout from api - react-native

I have developed an store app, my boss wants a feature that from wordpress panel select predefined layout to change the whole design and choose which category to be first or .... .
I have created all designs and components that needed, but I do not know how to change app layout that I recieved from api, is there any code or help for that. This change is not about color , its about changing whole home page app layout
Sorry for my english

Here is a simple example that you could implement.
You'll need to create custom complete components for each layout for the homepage.
Then you'll need to call the Wordpress API to get the layout name that needs to be displayed.
import React, { PureComponent } from 'react';
import { AppRegistry } from 'react-native';
import Layout1 from './components/Home/Layout1';
import Layout2 from './components/Home/Layout2';
import Layout3 from './components/Home/Layout3';
import Layout4 from './components/Home/Layout4';
import Loading from './components/Loading';
class HomePage extends PureComponent {
constructor(props) {
super(props);
this.state = {
layout: null
};
}
async componentDidMount() {
const response = await fetch('https://example.com/wp-json/whatever-api-endpoint')
.then(r => r.json());
this.setState({
layout: response
});
}
getContentElement = () => {
switch (this.state.layout) {
case 'layout_1': return <Layout1 />;
case 'layout_2': return <Layout2 />;
case 'layout_3': return <Layout3 />;
case 'layout_4': return <Layout4 />;
default: return <Loading />
}
};
render() {
const contentElement = this.getContentElement();
return (
<View>
{contentElement}
</View>
);
}
}
AppRegistry.registerComponent('MyApp', () => HomePage);

Related

how to implement crud axios in react native using react native class component? (API)

can anyone help me,
i am trying to make a simple CRUD using axios react native with class component,
to pass data from GET to Details data I succeeded, but when on the DETAIL page to retrieve only one data I had problems,
when I try console.log(dataTampung) / console.warn(dataTampung), the data array appears, but we want to display it instead of undefined.
import React, { Component } from 'react'
import { Text, View } from 'react-native'
import axios from 'axios'
export class DetailData extends Component {
constructor(props) {
super(props)
this.state = {
dataTampung: []
}
}
componentDidMount (){
this.getData();
}
getData = () => {
axios.get('http:my_local_ip_endpoind/api.php?on=detail&id='+this.props.route.params.id)
.then( response => {
this. setState({
dataTampung:response.data.data.result
})
})
.catch(function (error) {
console.log(error);
});
}
render() {
const { id } = this.props.route.params;
const { dataTampung } = this.state;
console.warn(dataTampung);
return (
<View>
<Text> This ID = {id} </Text>
<Text> Title = {`${dataTampung.title}`} </Text>
</View>
)
}
}
export default DetailData
And this is how it appears:enter image description here
Please help :(
I apologize in advance for my bad English.
You are trying to access the array with a dot notation. First, access the specific index in the array in thing case dataTampung[0] which will give you the object, then you can access the title as dataTampung[0].title.

React native How to execute function every time when i open page

I need to send request every time when i open page. Currently when i access page first time after load the app everything is ok, but if i go to another page and back after that request is not send it again.
You have to add focus listener so when you go back, It will refresh the data like
import * as React from 'react';
import { View } from 'react-native';
function AppScreen({ navigation }) {
React.useEffect(() => {
const unsubscribe = navigation.addListener('focus', () => {
// The screen is focused
// Call any action and update data
});
// Return the function to unsubscribe from the event so it gets removed on unmount
return unsubscribe;
}, [navigation]);
return <View />;
}
source : https://reactnavigation.org/docs/function-after-focusing-screen/
Here you go, example for a class based and functional based component to run something on every load of the screen.
import React, { useEffect } from "react";
import {View} from 'react-native'
//Functional Component
const App = () =>
{
useEffect(() =>
{
myAction();
}, [])
return (
<View>
</View>
);
}
//Class based Component
class App extends Component
{
componentDidMount()
{
this.myAction();
}
render()
{
return(
<View>
</View>
)
}
}

useTheme equivalent for class component

I would like to use the current theme in my class component.
According to the latest (RN 5.x) documentation, there is a useTheme() hook for that purposes. However, it doesn't mention any class equivalent.
I found ThemeContext.Consumer in RN 4.x but it is not available in 5.x anymore.
Is it possible to achieve the effect of useTheme() in some other way for a class component?
This is not so elegant, but it will do the job for you.
Here is my method to access the theme inside a class component:
import React from 'react'
import { SafeAreaView, Text } from 'react-native'
import { useTheme } from '#react-navigation/native'
export default class Home extends React.Component {
constructor(props) {
super(props)
this.state = {
theme: undefined
}
}
setTheme = theme => {
this.setState({theme})
}
render () {
console.log('theme', this.state.theme)
return (
<SafeAreaView>
<SetTheme setTheme={this.setTheme} />
<Text>Hello world</Text>
</SafeAreaView>
)
}
}
const SetTheme = ({ setTheme }) => {
const theme = useTheme()
React.useEffect(() => {
setTheme(theme)
return () => null
},[])
return null
}

How do I go back in webview? I am using the react-navigation package in react-native

I installed the react-navigation package in react-native
I have implemented tab navigation and one of them is implemented in webview format.
My problem is that if I press the back physical button on Android, I go from the app itself to the previous tab, not back from the webview.
I've already applied the back button for the webview on the internet, but I have not done that.
I tried to display the onNavigationStateChange log when debugging, but it was not updated when url was moved after it was loaded at first startup. Here is the code I implemented:
import React from "react";
import {BackHandler} from "react-native";
import {WebView} from "react-native-webview";
class SermonScreen extends React.Component {
constructor(props) {
super(props);
}
static navigationOptions = {
header: null
};
componentDidMount() {
BackHandler.addEventListener('hardwareBackPress', this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener('hardwareBackPress', this.handleBackButton);
}
_onNavigationStateChange(navState) {
console.log(navState);
this.setState({
canGoBack: navState.canGoBack
});
}
handleBackButton = () => {
console.log(this.state);
if (this.state.canGoBack === true) {
this.webView.goBack();
return true;
} else {
return false;
}
};
render() {
return (
<WebView
source={{uri: 'https://m.youtube.com/channel/UCw3kP3qCCF7ZpLUNzm_Q9Xw/videos' }}
ref={(webView) => this.webView = webView}
onNavigationStateChange={this._onNavigationStateChange.bind(this)}
/>
);
}
}
export default SermonScreen;
Following the official webview documnentation you could try to do this: https://github.com/react-native-community/react-native-webview/blob/master/docs/Guide.md#intercepting-hash-url-changes
In general you were almost there, however the way the YT navigation works made it impossible to be caught via the onNavigationStateChange, that's why we inject a JS code that intercepts these hash changes and posts a message to the parent component, we then catch it inside the onMessage handler and set the state variable properly. Copying the injectedJavaScript and onMessage properties to your example should solve your problem.
I prepared a component for you that seems to do what is needed:
* Sample React Native App
* https://github.com/facebook/react-native
*
* #format
* #flow
*/
import React, { Fragment } from "react";
import {
SafeAreaView,
StyleSheet,
ScrollView,
View,
Text,
BackHandler,
StatusBar
} from "react-native";
import { WebView } from "react-native-webview";
import {
Header,
LearnMoreLinks,
Colors,
DebugInstructions,
ReloadInstructions
} from "react-native/Libraries/NewAppScreen";
class App extends React.Component {
constructor(props) {
super(props);
this.startingUrl =
"https://m.youtube.com/channel/UCw3kP3qCCF7ZpLUNzm_Q9Xw/videos";
this.handleBackButton = this.handleBackButton.bind(this);
}
componentDidMount() {
BackHandler.addEventListener("hardwareBackPress", this.handleBackButton);
}
componentWillUnmount() {
BackHandler.removeEventListener("hardwareBackPress", this.handleBackButton);
}
handleBackButton = () => {
console.log(this.state);
const { canGoBack } = this.state;
if (canGoBack) {
this.webView.goBack();
return true;
} else {
return false;
}
};
render() {
return (
<Fragment>
<WebView
source={{ uri: this.startingUrl }}
style={{ marginTop: 20 }}
ref={webView => (this.webView = webView)}
injectedJavaScript={`
(function() {
function wrap(fn) {
return function wrapper() {
var res = fn.apply(this, arguments);
window.ReactNativeWebView.postMessage('navigationStateChange');
return res;
}
}
history.pushState = wrap(history.pushState);
history.replaceState = wrap(history.replaceState);
window.addEventListener('popstate', function() {
window.ReactNativeWebView.postMessage('navigationStateChange');
});
})();
true;
`}
onMessage={({ nativeEvent: state }) => {
if (state.data === "navigationStateChange") {
// Navigation state updated, can check state.canGoBack, etc.
this.setState({
canGoBack: state.canGoBack
});
}
}}
/>
</Fragment>
);
}
}
export default App;
The response above was perfect. I set the state true for canGoBack though; I was getting a null error, so:
constructor(props) {
super(props);
this.startingUrl = "https://app.vethorcardpag.com.br/GIF/login/0/";
this.state = {
canGoBack : true
}
this.handleBackButton = this.handleBackButton.bind(this);
}
Here is a simple solution using the magic of React's State.
Hope this helps.
import React, { useRef, useState } from 'react'
export default function Component () {
// This is used to save the reference of your webview, so you can control it
const webViewRef = useRef(null);
// This state saves whether your WebView can go back
const [webViewcanGoBack, setWebViewcanGoBack] = useState(false);
const goBack = () => {
// Getting the webview reference
const webView = webViewRef.current
if (webViewcanGoBack)
// Do stuff here if your webview can go back
else
// Do stuff here if your webview can't go back
}
return (
<WebView
source={{ uri: `Your URL` }}
ref={webViewRef}
javaScriptEnabled={true}
onLoadProgress={({ nativeEvent }) => {
// This function is called everytime your web view loads a page
// and here we change the state of can go back
setWebViewcanGoBack(nativeEvent.canGoBack)
}}
/>
)
}
Original answer
https://stackoverflow.com/a/74500469/7823800

Is there a way to read the options before use the mergeOptions function in react native navigation v2?

Is there a way to read the options before using the mergeOptions function.
I'm trying to add a sideMenu that opens and closes with the same button. But to handle that logic, Instead of making use of redux, I want to read the options before the merge, so I can simply do something like visible: !pastVisible.
navigationButtonPressed({ buttonId }) {
Navigation.mergeOptions(this.props.componentId, {
sideMenu: {
'left': {
visible: false
}
}
});
console.log(`Se presiono ${buttonId}`);
}
So basically I want to read the value of the visible option before changed it.
By now, I can only achieve this using redux.
import React, {Component} from 'react';
import {View, Text} from 'react-native';
import { Navigation } from 'react-native-navigation';
import { connect } from 'react-redux';
import { toggleSideMenu } from './../../store/actions/index';
class SideDrawer extends Component {
constructor(props) {
super(props);
Navigation.events().registerComponentDidDisappearListener(({ componentId }) => {
this.props.toggleSideMenu(false);
});
}
render() {
return (
<View>
<Text>This is the sidedrawer</Text>
</View>
);
}
}
const mapDispatchToProps = dispatch => {
return {
toggleSideMenu: (visible) => dispatch(toggleSideMenu(visible))
};
};
export default connect(null, mapDispatchToProps)(SideDrawer);
Then I just add the listeners to the sidemenu component. Depending on the case, I update the current state of the component (visible or not).
Finally on the components where I want to use the side drawer button I just implement the navigationButtenPressed method. Then I just call the reducer to know the current visible state and toggled it.
navigationButtonPressed({ buttonId }) {
const visible = !this.props.sideMenu;
Navigation.mergeOptions(this.props.componentId, {
sideMenu: {
'left': {
visible: visible
}
}
});
this.props.toggleSideMenu(visible);
}
If there is a more easy way to achieve this I'll be glad to know about it.