I am new in Ract Native and I am trying to build a small app using react native navigation.
I can see in the movie-app example provided on their site (react native navigation) that they do not use a componentWillMount function in app.js, but they have a startApp() function instead, called in the constructor.
I am basically trying to define the firebase configuration in the componentWillMounth function, but a simple console log shows that the function is somehow never run.
I would like to set up the app properly, for best performance, so I am wondering if using the startApp function is basically the same, no need to use a componentWillMount function?
Update: Code below
index.ios.js
import App from './src/app';
const app = new App();
app.js
import ...
class App extends Component {
state = {
loggedIn: null
}
constructor(props) {
super(props);
this.startApp();
}
componentWillMount() {
console.log('COMPONENT WILL MOUNT');
// Initialize Firebase
const config = {
...
...
};
firebase.initializeApp(config);
}
startApp() {
console.log('START APP');
// Initialize Firebase here???
const tabs = [
...
];
if (this.state.loggedIn) {
Navigation.startTabBasedApp({
tabs,
tabsStyle: {
...
}
});
} else {
Navigation.startSingleScreenApp({
...
});
}
} // startApp
}
export default App;
Your componentWillMount is not being executed because you are not using your component within the React render lifecycle (you are instantiating it not in a render, but with new, which will only run the constructor of the component. Move it to your index render method, like this:
class EntryPoint extends React.Component {
render(){
<App />
}
}
AppRegistry.registerComponent('MyApp', ()=>EntryPoint);
Related
I'm building a simple Next.js website that consumes the spacex graphql API, using apollo as a client. I'm trying to make an api call, save the returned data to state and then set that state as context.
Before I save the data to state however, I wanted to check that my context provider was actually providing context to the app, so I simply passed the string 'test' as context.
However, up[on trying to extract this context in antoher component, I got the following error:
Error: The default export is not a React Component in page: "/"
My project is set up as follows, and I'm thinking I may have put the context file in the wrong place:
pages
-api
-items
-_app.js
-index.js
public
styles
next.config.js
spacexContext.js
Here's the rest of my app:
spaceContext.js
import { useState,useEffect,createContext } from 'react'
import { ApolloClient, InMemoryCache, gql } from "#apollo/client"
export const LaunchContext = createContext()
export const getStaticProps = async () => {
const client = new ApolloClient({
uri: 'https://api.spacex.land/graphql/',
cache: new InMemoryCache()
})
const { data } = await client.query({
query: gql`
query GetLaunches {
launchesPast(limit: 10) {
id
mission_name
launch_date_local
launch_site {
site_name_long
}
links {
article_link
video_link
mission_patch
}
rocket {
rocket_name
}
}
}
`
});
return {
props: {
launches: data.launchesPast
}
}
}
const LaunchContextProvider = (props) => {
return(
<LaunchContext.Provider value = 'test'>
{props.children}
</LaunchContext.Provider>
)
}
export default LaunchContextProvider
_app.js
import LaunchContextProvider from '../spacexContext'
import '../styles/globals.css'
function MyApp({ Component, pageProps }) {
return (
<LaunchContextProvider>
<Component {...pageProps} />
</LaunchContextProvider>
)
}
export default MyApp
Any suggestions on why this error is appearing and how to fix it?
The problem: i have many sagas that do not handle an 401 error in response status, and now i have to deal with it. I have apiservice based on apisause and i can write an response monitor with it to handle 401 error (like interceptors in axios). But i cant dispatch any action to store to reset user data, for example, because there is no store context in apiservice. How to use dispatch function in apiservice layer? Or use put() function in every saga when i recieve 401 response status is the only right way?
you can use refs for using navigation in 'apisauce' interceptors
this is my code and it works for me ;)
-- packages versions
#react-navigation/native: ^6.0.6
#react-navigation/native-stack: ^6.2.5
apisauce: ^2.1.1
react: 17.0.2
react-native: ^0.66.3
I have a main file for create apisauce
// file _api.js :
export const baseURL = 'APP_BASE_URL';
import { create } from 'apisauce'
import { setAPIInterceptors } from './interceptors';
const APIClient = create({ baseURL: baseURL })
setAPIInterceptors(APIClient)
and is file interceptors.js I'm watching on responses and manage them:
// file interceptors.js
import { logout } from "../redux/actions";
import { store } from '../redux/store';
import AsyncStorage from '#react-native-async-storage/async-storage';
export const setAPIInterceptors = (APIClient) => {
APIClient.addMonitor(monitor => {
// ...
// error Unauthorized
if(monitor.status === 401) {
store.dispatch(logout())
AsyncStorage.clear().then((res) => {
RootNavigation.navigate('login');
})
}
})
}
then I create another file and named to 'RootNavigation.js' and create a ref from react-native-navigation:
// file RootNavigation.js
import { createNavigationContainerRef } from '#react-navigation/native';
export const navigationRef = createNavigationContainerRef()
export function navigate(name, params) {
if (navigationRef.isReady()) {
navigationRef.replace(name, params);
}
}
// add other navigation functions that you need and export them
then you should to set some changes in you App.js file:
import { NavigationContainer } from '#react-navigation/native';
import { navigationRef } from './RootNavigation';
export default function App() {
return (
<NavigationContainer ref={navigationRef}>{/* ... */}</NavigationContainer>
);
}
finally in anywhere you can call this function for use react native navigations
full focument is in here that explain how to Navigating without the navigation prop
Navigating without the navigation prop
I've recent switched over to Quasar v2 and I'm having trouble getting the info I need for the vue apollo setup. I am using https://apollo.vuejs.org/guide/installation.html#_1-apollo-client to try and install vue apollo into the framework using the boot file.
This is my boot/apollo.ts file
import { boot } from 'quasar/wrappers';
import ApolloClient from 'apollo-boost';
import VueApollo from 'vue-apollo';
const apollo = new ApolloClient({
uri: 'https://api.graphcms.com/simple/v1/awesomeTalksClone',
});
const apolloProvider = new VueApollo({
defaultClient: apollo,
});
export default boot(({ app }) => {
// for use inside Vue files (Options API) through this.$apollo
app.config.globalProperties.$apollo = apollo;
// ^ ^ ^ this will allow you to use this.$apollo (for Vue Options API form)
// so you won't necessarily have to import apollo in each vue file
});
export { apollo, VueApollo, apolloProvider };
And this is where I am trying to use it:
import { Vue } from 'vue-class-component';
export default class LoginPage extends Vue {
public login() {
console.log(this.$apollo);
}
}
The error I'm getting is
Property '$apollo' does not exist on type 'LoginPage'.
I can see in the comment for the globalProperties it mentions the vue options api. Not sure if this is happening because I use vue-class-component.
I ended up added this below the export
declare module '#vue/runtime-core' {
interface ComponentCustomProperties {
$apollo: FunctionConstructor;
}
}
When I create a simple app, I found that next.js will automatically do the server side render.
But when I tried to fetch the data from backend, I found that server side won't get the data.
How to fetch the data from server side? So that I can do the server side render?
components/test.js
import React, { Component } from 'react';
class Test extends Component {
constructor(){
super();
this.state={
'test':''
}
}
setTest(){
axios.get(serverName+'/api/articles/GET/test').then(response=>{
let test;
test = response.data.test;
this.setState({test});
}).catch(function (error) {
console.log(error);
});
}
}
render() {
return (
<div>
{this.state.test}
</div>
);
}
}
export default Test;
backend is just like following:
function getTest(Request $request){
return response()->json(['test'=>'this is a test']);
}
Next.js uses getInitialProps that is executed on the server on initial load only.
From docs
For the initial page load, getInitialProps will execute on the server
only. getInitialProps will only be executed on the client when
navigating to a different route via the Link component or using the
routing APIs.
All other lifecycle methods/actions on React components (componentDidMount, onClick, onChange etc) are executed on the client side.
Example code
class Test extends Component {
static async getInitialProps() {
const response = await axios.get(serverName + '/api/articles/GET/test');
return { test: response.data.test }
}
render() {
return <div>{this.props.test}</div>;
}
}
export default Test;
Like below. I would recomend to use getInitialProps. This is recommended approach by next.js to get data at server.
import React from 'react'
export default class extends React.Component {
static async getInitialProps({ req }) {
axios.get(serverName+'/api/articles/GET/test').then(response=>{
let test;
test = response.data.test;
return { test }
}).catch(function (error) {
return { response }
});
}
render() {
return (
<div>
Hello World {this.props.test.name}
</div>
)
}
}
I'm trying to call dispatch from a react component that is connect to redux. For whatever reason i'm unable to call this.props.dispatch from this component. However the showPopup action is working fine in the component?
Reading the docs it says that whenever you have the connect(), you should be able to call this.props.dispatch. Anything I'm missing here?
import React, { Component } from 'react';
import { connect } from 'react-redux';
// Actions
import { showPopup } from '../../../actions';
class Channels extends Component {
render() {
console.log(this.props.dispatch); // <- undefined (?)
return <div>some stuff</div>;
}
}
export default connect(null, { showPopup })(Channels);
Update 1
The following makes it work, is there no way to shorten this?
function mapDispatchToProps(dispatch) {
let actions = bindActionCreators({ showPopup });
return { ...actions, dispatch };
}
Update 2
export default connect(null, (dispatch) => bindActionCreators({ showPopup, dispatch }, dispatch))(Channels);
Your first code should work just change your this.props.dispatch to this.props.showPopup.
If you pass a second argument to connect method, it will map those actions as props. connect(null, { showPopup, otherAction, someAction })(Channels);, you can use this.props.showPopup() or this.props.otherAction or this.props.someAction to dispatch the action
If you just do connect()(Channels); then you need to use this.props.dispatch(showPopup(...)) or this.props.dispatch(otherAction()) or this.props.dispatch(someAction())
That is because you are defining mapDispatchToProps as an object.
The documentation says that:
Your component will no longer receive dispatch as a prop