React Native Net Info it works once - javascript

native-info package like tutorial but just enters once and initial render, I implemented App.js is my initial rendering page and I use redux and react nativagiton to App.js return method I confuse why console.warn triggered once and initial render, my App.js code like below
import {SafeAreaProvider} from 'react-native-safe-area-context';
import {Provider} from 'react-redux';
import {PersistGate} from 'redux-persist/integration/react';
import {NavigationContainer} from '#react-navigation/native';
import { SafeAreaProvider } from "react-native-safe-area-context";
import { Provider } from "react-redux";
import { PersistGate } from "redux-persist/integration/react";
import { NavigationContainer } from "#react-navigation/native";
export default function App() {
let navigator;
const [netInfo, setNetInfo] = useState("");
const [netConnection, setNetConnection] = useState(false);
useEffect(() => {
const unsubscribe = NetInfo.addEventListener((state) => {
setNetInfo({
isConnected: state.isConnected,
});
});
return () => {
unsubscribe();
};
}, []);
useEffect(() => {
console.warn(netInfo.isConnected);
if (netInfo.isConnected === undefined) {
if (netInfo.isConnected) {
setNetConnection(true);
} else {
setNetConnection(false);
}
}
}, [netInfo]);
return (
<Provider store={store}>
{netConnection && <RnModal show={netConnection} />}
<PersistGate loading={null} persistor={persistor}>
<SafeAreaProvider>
<NavigationContainer
ref={(nav) => {
navigator = nav;
}}
>
<Navigator />
</NavigationContainer>
</SafeAreaProvider>
</PersistGate>
</Provider>
);
}

Related

React context, I get an error when I refresh the page

What I'm trying to do is to call my service on the main page and then assign context to the response and print it in another component. I can print but when I refresh the page I get an error.
home.js
import React, { useContext, useEffect } from 'react';
import { PolicyContext } from 'contexts/PolicyContext';
import { PolicyService } from 'services/PolicyService';
const Home = () => {
const { policyData, setPolicyData } = useContext(PolicyContext);
const activiesPolicyExampleReq = {
nationalId: '59104492600',
};
useEffect(() => {
PolicyService.getActivePolicies(activiesPolicyExampleReq).subscribe(
(response) => {
setPolicyData(response);
}
);
}, []);
}
PolicyContext.js
import React, { createContext, useMemo, useState } from 'react';
export const PolicyContext = createContext(undefined);
const PolicyContextProvider = (props) => {
const [policyData, setPolicyData] = useState();
console.log('PC');
return (
<PolicyContext.Provider
value={useMemo(() => {
return ({
policyData,
setPolicyData,
});
}, [{ policyData, setPolicyData }])}
>
{props.children}
</PolicyContext.Provider >
);
};
export default PolicyContextProvider;
App.js
import { Route, Router } from 'react-router-dom';
import AppRouter from 'routes/AppRouter';
import { CookiesProvider } from 'react-cookie';
import Header from 'modules/Header';
import Login from 'pages/login/login';
import Onboarding from './pages/onboarding/onboarding';
import PolicyContextProvider from './contexts/PolicyContext';
import React from 'react';
import Theme from 'theme/Theme';
import { history } from './libs/History';
export default function App() {
return (
<Theme>
<CookiesProvider>
<PolicyContextProvider>
<Router history={history}>
<Route exact path={['/onboarding']} component={Onboarding} />
<Route exact path={['/login']} component={Login} />
<Header />
<AppRouter />
</Router>
</PolicyContextProvider>
</CookiesProvider>
</Theme>
);
}
the component i want to print
const { policyData, setPolicyData } = useContext(PolicyContext);
console.log(policyData);
<TabPanel value={value} index={0}>
<PolicyCarousel
policyList={
policyData.activePoliciesMap
? policyData.activePoliciesMap[policiesMapType]
: null
}
policyType={0}
/>
</TabPanel>
error in console:
Cannot read properties of undefined (reading 'activePoliciesMap')

Accessing LaunchDarkly flags from React.JS

I am trying to access LaunchDarkly flags from my App context. The code looks like:
import { useState, useEffect } from 'react';
import { Helmet } from 'react-helmet';
import { MuiPickersUtilsProvider } from '#material-ui/pickers';
import DateFnsUtils from '#date-io/date-fns';
import { ApolloProvider } from 'react-apollo';
import { Route, Router, Switch } from 'react-router-dom';
import { withLDProvider } from 'launchdarkly-react-client-sdk';
import { Loading } from '#ap/owl-ui-controls';
import { useAuth0 } from './context/Authentication';
import LabelContext from './context/LabelContext';
import { CommunityByNameContext } from './context/CommunityByNameContext';
import { segment_init } from './utils/segment';
import withConfig, { ConfigEnum } from './utils/withConfig';
import client from './utils/graphQLClient';
import labels from './config/labels';
import CurrentUser from './services/CurrentUser';
import Layout from './Layout';
import history from './utils/history';
import { SearchCommunity } from './common/Filters/SearchNameFilter/findCommunitiesQuery';
import AmplitudeContext, { AmplitudeData } from './context/AmplitudeContext';
import { DisclosuresContextProvider } from './context/DisclosuresContext';
import placeService from './services/placesService';
import { FeaturedCommunitiesIdsProvider } from './context/FeaturedCommunitiesIdsContext';
import { optimizelyInit } from './utils/optimizely';
import { FamilyFileContextProvider } from './context/FamilyFileContext';
const segmentKey = withConfig(ConfigEnum.SEGMENT_KEY);
const currentUserString = localStorage.getItem('CURRENT_USER');
const App = () => {
const { loading } = useAuth0();
const [currentUser, setCurrentUser] = useState(currentUserString ? JSON.parse(currentUserString) : null);
const [communityByName, setCommunityByName] = useState<SearchCommunity | null>(null);
const [amplitude, setAmplitude] = useState<AmplitudeData>({});
useEffect(() => {
placeService.init();
}, []);
if (loading) {
return <Loading />;
}
return (
<>
<Helmet>
<title>Beacon</title>
<script type="text/javascript">{optimizelyInit(flags)}</script>
<script type="text/javascript">{segment_init(segmentKey, currentUser)}</script>
</Helmet>
<LabelContext.Provider value={labels}>
<CommunityByNameContext.Provider value={{ communityByName, setCommunityByName }}>
<FeaturedCommunitiesIdsProvider>
<AmplitudeContext.Provider value={{ amplitude, setAmplitude }}>
<MuiPickersUtilsProvider utils={DateFnsUtils}>
<ApolloProvider client={client}>
{/* #ts-ignore */}
<CurrentUser onUserChanged={(currentUser: any) => setCurrentUser(currentUser)}>
<FamilyFileContextProvider>
<DisclosuresContextProvider>
<Router history={history}>
<Switch>
<Route path="/communities" component={Layout} />
</Switch>
</Router>
</DisclosuresContextProvider>
</FamilyFileContextProvider>
</CurrentUser>
</ApolloProvider>
</MuiPickersUtilsProvider>
</AmplitudeContext.Provider>
</FeaturedCommunitiesIdsProvider>
</CommunityByNameContext.Provider>
</LabelContext.Provider>
</>
);
};
export default withLDProvider({
clientSideID: withConfig(ConfigEnum.LD_CLIENT_SIDE_ID),
})(App);
My nested components, like for example <CurrentUser /> get LD flags, and I am able to access them as:
const CurrentUser = ({ children, flags, onUserChanged })
However, I also need LD flags inside <App /> so I could do:
<Helmet>
<title>Beacon</title>
{flags.optimizely && <script type="text/javascript">{optimizelyInit(flags)}</script>}
<script type="text/javascript">{segment_init(segmentKey, currentUser)}</script>
</Helmet>
I have tried accessing flags with const App = ({ flags }), but the value is always undefined.
I even tried sticking the below into a component
const DocumentHead = ({ flags, segmentKey, currentUser }) => (
<Helmet>
<title>Beacon</title>
<script type="text/javascript">{optimizelyInit(flags)}</script>
<script type="text/javascript">{segment_init(segmentKey, currentUser)}</script>
</Helmet>
);
Flags are still undefined.
Suggestions?
Apparently, there is a useFlags hook. We can get flags as:
const flags = useFlags();
This can be called from the <App /> component.

Cannot connect component to redux store

In my profile page I have 3 cards, which means 3 react-components.
I am new to React.js and recently set up redux in my application. So the problem is two of them (cards) successfully connected to redux store, but third card can't for unknown reasons, can you help me please?
Redux store just returns undefined only for Card3.js
Hero.js (Profile)
import React, { useState, useEffect } from "react"
import FadeIn from 'react-fade-in';
import { Redirect } from 'react-router-dom'
import { Container, Row } from 'react-bootstrap'
import { getUserProfile } from "../../services/user.service";
import { connect } from "react-redux";
import './profile.css'
import LCard1 from "./cards/card1/LCard1"
import Card1 from "./cards/card1/Card1"
import Card2 from "./cards/card2/Card2"
import Card3 from "./cards/card3/Card3"
const Hero = (props) => {
const [userInfo, setUserInfo] = useState({username: ''})
const [isLoading, setIsLoading] = useState(true)
const getUser = async () => {
console.log()
await getUserProfile(props.uid)
.then(res => {
setUserInfo(res)
setIsLoading(false)
})
}
useEffect(() => {
if (userInfo)
getUser()
}, [])
return (
<>
<FadeIn transitionDuration={1000}>
{props.authenticated ? (
<section className="profile-cards">
<Container fluid >
<Row>
{isLoading ? (
<LCard1 />
) : (
<Card1 user={userInfo} />
)}
<Card3 />
</Row>
<Row>
<Card2 />
</Row>
</Container>
</section>
) : (
<Redirect to="/signin" />
)}
</FadeIn>
</>
)
}
const mapStateToProps = (state) => {
return {
uid: state.authReducer.uid,
authenticated: state.authReducer.authenticated
}
}
const mapDispatchToProps = (dispatch) => {
return {
logout: () => {
dispatch({
type: 'SIGNOUT_SUCCESS'
})
}
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(Hero)
Card3.js
import React from 'react'
import { connect } from "react-redux";
import CreateAdvertisement from './content/create.advert/CreateAdvertisement'
import MyMessages from './content/my.messages/MyMessages';
import MySettings from './content/my.settings/MySettings';
import MyVerfifcation from './content/my.verif/MyVerfifcation';
import './card3.css'
const Card3 = (props) => {
return (
<div>
<p>Test: {props.username}</p>
<section className="card3">
<div className="card3-box">
<div>
<MySettings />
</div>
</div>
</section>
</div>
)
}
const mapStateToProps = (state) => {
return {
key: state.authReducer.username
}
}
export default connect(
mapStateToProps
)(Card3)
store.js
import { configureStore } from '#reduxjs/toolkit'
import { persistReducer } from 'redux-persist'
import storage from 'redux-persist/lib/storage'
import thunk from 'redux-thunk'
import reducers from './reducers/root.reducer'
const persistConfig = {
key: 'root',
storage: storage,
blacklist: ['sidebarReducer']
}
const persistedReducer = persistReducer(persistConfig, reducers)
const store = configureStore({
reducer: persistedReducer,
devTools: process.env.NODE_ENV !== 'production',
middleware: [thunk]
})
export default store
index.js
import React from 'react'
import ReactDOM from 'react-dom'
import App from './components/App'
import { Provider } from 'react-redux'
import { PersistGate } from 'redux-persist/integration/react'
import { persistStore } from 'redux-persist'
import store from './store/store'
let persistor = persistStore(store)
ReactDOM.render(
<Provider store={store}>
<PersistGate loading={null} persistor={persistor}>
<App />
</PersistGate>
</Provider>,
document.getElementById('root')
);
import React, { Component } from 'react';
import { View, Text,ScrollView } from 'react-native';
import { Provider } from 'react-redux'
import store from './src/Redux/Store'
import MainNavigation from './src/components/Navigation/Navigation';
class App extends Component {
constructor(props) {
super(props);
this.state = {
};
}
render() {
return (
<Provider store={store}>
<MainNavigation/>
</Provider>
);
}
}
export default App;
First your all screens should under a navigation then
follow this code This will work for you Thanks.

How to fix the Rendered more hooks than during the previous render using react hook

index.tsx
import useUser from '#services/users';
import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next';
function App() {
const { t } = useTranslation();
const { getAll } = useUser();
const [ rowData, setRowData ] = useState([]);
useEffect(() => {
let ignore = false;
(async function setAllData() {
let response = await getAll({ length: 9999 });
})()
if (!ignore) {
setRowData(response['data']['data']);
}
})()
return () => {
ignore = true;
}
}, [])
return (
<>
<button>{t('create')}</button>
{
rowData.map((item, index) => (
<div key={index}>
{item.firstName}<br/>
</div>
))
}
</>
)
}
export default App;
user.tsx
export default function useUser() {
const creds = useCredentials();
Axios.defaults.baseURL = serverConfig[creds.server].api;
return {
getAll: (params?: object) => Axios.get(API_URL + (params ? getQueryParams(params) : ''))
}
}
I'm having trouble when I added the react-i18next which is the useTranslation. The error message is Rendered more hooks than during the previous render. when added the translation. How do I fix on it?
I had the same issue with useTranslation.
For me the cause was wrapping the i18next init script in a function calling that inside App.tsx instead of just exporting i18n and importing it directly inside index.tsx
So NOT:
App.tsx
import initI18n from './i18n.ts'
const App = () => {
initI18n()
return <div>Party</div>
}
BUT THIS WORKED
index.tsx
import './i18n.ts'
ReactDOM.render(
<React.StrictMode>
<Provider store={store}>
<BrowserRouter>
<App />
</BrowserRouter>
</Provider>
</React.StrictMode>,
document.getElementById('root')
);

React-Router v4 rendering wrong component but matching correctly

I've got a sidebar with two buttons, 'test' and 'about'. Test (rocket icon) is rendered at '/test', and About (home icon) is rendered at '/'.
They're both located at the root of the app and are nested within a component.
When I start at '/' and click the Link to="/test" it always loads the 'About' component, and when I check the props for the componentDidMount of 'About', the match object contains match data for "/test".
Only when I refresh does it render the proper component, 'Test', again. Any idea why this is happening?
AppRoutes.js:
export class AppRoutes extends React.Component {
render() {
return (
<div>
<Switch>
<Route
exact path="/"
render={(matchProps) => (
<LazyLoad getComponent={() => import('pages/appPages/About')} {...matchProps} />
)}
/>
<Route
path="/login"
render={(matchProps) => (
<LazyLoad getComponent={() => import('pages/appPages/Login')} {...matchProps} />
)}
/>
<Route
path="/register"
render={(matchProps) => (
<LazyLoad getComponent={() => import('pages/appPages/Register')} {...matchProps} />
)}
/>
<Route
path="/test"
render={(matchProps) => (
<LazyLoad getComponent={() => import('pages/appPages/Test')} {...matchProps} />
)}
/>
...
AboutPage.js && TestPage.js (duplicates except for component name):
import React from 'react';
import SidebarContainer from 'containers/SidebarContainer';
import SidebarPageLayout from 'styles/SidebarPageLayout';
export const About = (props) => {
console.log('About Loading: ', props);
return (
<SidebarPageLayout>
<SidebarContainer />
<div>About</div>
</SidebarPageLayout>
);
}
export default About;
SidebarContainer.js:
import React from 'react';
import PropTypes from 'prop-types';
import _ from 'lodash';
import Sidebar from 'sidebar/Sidebar';
import HamburgerButton from 'sidebar/HamburgerButton';
import AboutButton from 'sidebar/AboutButton';
import ProfileButton from 'sidebar/ProfileButton';
import TestButton from 'sidebar/TestButton';
export class SidebarContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
sidebarIsOpen: false,
sidebarElements: [],
};
}
componentDidMount() {
if (!this.props.authenticated) {
this.setState({
sidebarElements: _.concat(this.state.sidebarElements, HamburgerButton, ProfileButton, AboutButton, TestButton),
});
}
}
toggleSidebarIsOpenState = () => {
this.setState({ sidebarIsOpen: !this.state.sidebarIsOpen });
}
render() {
const { authenticated, sidebarIsOpen, sidebarElements} = this.state;
return (
<div>
<Sidebar
authenticated={authenticated}
sidebarIsOpen={sidebarIsOpen}
sidebarElements={_.isEmpty(sidebarElements) ? undefined: sidebarElements}
toggleSidebarIsOpenState={this.toggleSidebarIsOpenState}
/>
</div>
);
}
}
SidebarContainer.propTypes = {
authenticated: PropTypes.bool,
};
export default SidebarContainer;
Sidebar.js:
import React from 'react';
import _ from 'lodash';
import PropTypes from 'prop-types'
import SidebarStyles from '../styles/SidebarStyles';
export const Sidebar = (props) => {
if (props && props.sidebarElements) {
return (
<SidebarStyles sidebarIsOpen={props.sidebarIsOpen}>
{_.map(props.sidebarElements, (value, index) => {
return React.createElement(
value,
{
key: index,
authenticated: props.authenticated,
sidebarIsOpen: props.sidebarIsOpen,
toggleSidebarIsOpenState: props.toggleSidebarIsOpenState,
},
);
})}
</SidebarStyles>
);
}
return (
<div></div>
);
}
Sidebar.propTypes = {
authenticated: PropTypes.bool,
sidebarIsOpen: PropTypes.bool,
sidebarElements: PropTypes.array,
toggleSidebarIsOpenState: PropTypes.func,
};
export default Sidebar;
TestButton.js:
import React from 'react';
import PropTypes from 'prop-types';
import Icon from 'react-fontawesome';
import {
Link
} from 'react-router-dom';
export const TestButton = (props) => {
return (
<Link to="/test">
<Icon name='rocket' size='2x' />
</Link>
);
}
export default TestButton;
AboutButton.js:
import React from 'react';
import PropTypes from 'prop-types';
import Icon from 'react-fontawesome';
import {
Link
} from 'react-router-dom';
export const AboutButton = (props) => {
return (
<Link to="/">
<Icon name='home' size='2x' />
</Link>
);
}
export default AboutButton;
No refresh, just constant clicking on the '/test' route from the '/' route:
after refresh:
Edit:
Root components:
Edit:
store.js:
import {
createStore,
applyMiddleware,
compose,
} from 'redux';
import createSagaMiddleware from 'redux-saga';
import { rootReducer } from './rootReducers';
import { rootSaga } from './rootSagas';
// sagas
const sagaMiddleware = createSagaMiddleware();
// dev-tools
const composeEnhancers = typeof window === 'object' && (
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ ? (
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__
) : compose
);
export function configureStore() {
const middlewares = [
sagaMiddleware,
];
const store = createStore(
rootReducer,
{},
composeEnhancers(applyMiddleware(...middlewares))
);
sagaMiddleware.run(rootSaga);
return store;
}
export const store = configureStore();
index.js (root):
import React from 'react';
import { Provider } from 'react-redux';
import ReactDOM from 'react-dom';
import { BrowserRouter } from 'react-router-dom';
import { store } from './store';
import AppContainer from 'containers/AppContainer';
ReactDOM.render(
<Provider store={store}>
<BrowserRouter>
<AppContainer />
</BrowserRouter>
</Provider>,
document.getElementById('root')
);
AppContainer:
import React from 'react';
import { withRouter } from 'react-router-dom';
import { connect } from 'react-redux';
import { logout, verifyToken } from './actions';
import { selectAuthenticated, selectAuthenticating } from './selectors';
import AppRoutes from 'routes/AppRoutes';
export class AppContainer extends React.Component {
constructor(props) {
super(props);
this.state = { loaded: false };
}
componentDidMount() {
const token = localStorage.getItem('jwt');
if (token) {
this.props.verifyToken(token, () => this.setState({ loaded: true }));
} else {
this.setState({ loaded: true });
}
}
render() {
if (this.state.loaded) {
return (
<AppRoutes
authenticated={this.props.authenticated}
authenticating={this.props.authenticating}
logout={this.props.logout}
/>
);
} else {
return <div>Loading ...</div>
}
}
}
function mapStateToProps(state) {
return {
authenticated: selectAuthenticated(state),
authenticating: selectAuthenticating(state),
};
}
function mapDispatchToProps(dispatch) {
return {
verifyToken: (token = '', callback = false) => dispatch(verifyToken(token, callback)),
logout: () => dispatch(logout()),
};
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(AppContainer));
Edit 2 for LazyLoad:
services/LazyLoad/index.js:
import React from 'react';
export class LazyLoad extends React.Component {
constructor(props) {
super(props);
this.state = {
AsyncModule: null,
};
}
componentDidMount() {
this.props.getComponent() // getComponent={() => import('./someFile.js')}
.then(module => module.default)
.then(AsyncModule => this.setState({AsyncModule}))
}
render() {
const { loader, ...childProps } = this.props;
const { AsyncModule } = this.state;
if (AsyncModule) {
return <AsyncModule {...childProps} />;
}
if (loader) {
const Loader = loader;
return <Loader />;
}
return null;
}
}
export default LazyLoad;
Your problem lies with LazyLoad component. For both "/" or "test" paths, what AppRoutes component ultimately renders is a LazyLoad component. Because Route and Switch just conditionally render their children. However, React can't differentiate "/" LazyLoad component and "/test" LazyLoad component. So the first time it renders LazyLoad component and invokes the componentDidMount. But when route changes, React consider it as a prop change of previously rendered LazyLoad component. So it just invokes componentWillReceiveProps of previous LazyLoad component with new props instead of unmounting previous one and mount a new one. That's why it continuously show About component until refresh the page.
To solve this problem, if the getComponent prop has changed, we have to load the new module with new getComponent inside the componentWillReceiveProps. So we can modify the LazyLoad as follows which have a common method to load module and invoke it from both componentDidMount and componentWillReceiveProps with correct props.
import React from 'react';
export class LazyLoad extends React.Component {
constructor(props) {
super(props);
this.state = {
AsyncModule: null,
};
}
componentDidMount() {
this.load(this.props);
}
load(props){
this.setState({AsyncModule: null}
props.getComponent() // getComponent={() => import('./someFile.js')}
.then(module => module.default)
.then(AsyncModule => this.setState({AsyncModule}))
}
componentWillReceiveProps(nextProps) {
if (nextProps.getComponent !== this.props.getComponent) {
this.load(nextProps)
}
}
render() {
const { loader, ...childProps } = this.props;
const { AsyncModule } = this.state;
if (AsyncModule) {
return <AsyncModule {...childProps} />;
}
if (loader) {
const Loader = loader;
return <Loader />;
}
return null;
}
}
export default LazyLoad;

Categories

Resources