Accessing LaunchDarkly flags from React.JS - javascript

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.

Related

Uncaught TypeError: Cannot read properties of undefined (reading 'params') while using axios and react-router-dom

It's the HomePage component of ReactJS
import React from 'react';
import axios from 'axios';
import { useState, useEffect } from 'react';
import { useNavigate,useParams } from 'react-router-dom';
import { Main } from '../components/Main';
import { Controls } from '../components/Controls';
import { ALL_COUNTRIES } from '../config';
import { List } from '../components/List';
import { Card } from '../components/Card';
import { Details } from './Details';
export const HomePage = () => {
const [countries,setCountries] = useState([]);
const navigate = useNavigate();
useEffect(() => {
axios.get(ALL_COUNTRIES).then(({data})=>setCountries(data))
},[]);
return (
<>
<Controls/>
<List>
{
countries.map((c) => {
const countryInfo = {
img: c.flags.png,
name: c.name,
info: [
{
title:'Population',
description:c.population.toLocaleString(),
},
{
title:'Region',
description:c.region,
},
{
title:'Flag',
description:c.capital,
},
],
};
return (
<Card
key={c.name}
onClick={(e) => {
navigate('/country/${c.name}');
}}
{...countryInfo}
/>
)
})
}
</List>
</>
);
};
It's second components Details
import React from 'react';
import { useParams } from 'react-router-dom';
export const Details = ({match,params}) => {
const { name } = useParams();
return (
<div>
Details {match.params.name}
</div>
);
};
config.js
const BASE_URL = 'https://restcountries.com/v2/';
export const ALL_COUNTRIES=BASE_URL+"all?fields=name,flags,population,capital,region";
export const searchByContry=(name)=>BASE_URL+'name/'+name;
export const filterByCode=(code)=>BASE_URL+'alpha?code'+code.join('');
APP.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import axios from 'axios';
import { Route,Routes,Router,useParams} from 'react-router-dom';
import {useState, useEffect} from 'react';
import './App.css';
import styled from 'styled-components';
import Header from './components/Header';
import { Main } from './components/Main';
import {NotFound} from './pages/NotFound';
import { HomePage } from './pages/HomePage';
import { Details } from './pages/Details';
function App() {
return (
<>
<Header/>
<Main>
<Routes>
<Route path="/" element={<HomePage/>}/>
<Route path="country/:name" element={<Details/>}/>
<Route path="*" element={<NotFound/>}/>
</Routes>
</Main>
</>
);
}
export default App;
HomePage itself looks like this
but when I click on flag/card it sends me on second page as expected but gives me this error
[2]:https://i.stack.imgur.com/39HEw.png
Also, I'm using react-router-domV6 and Axios
and this API https://restcountries.com/v2/all
also both Components are in
APP.js
Details is trying to read params from an undefined object, props.match in this case.
<Route path="country/:name" element={<Details />} /> // <-- no props passed!
...
import React from 'react';
import { useParams } from 'react-router-dom';
export const Details = ({ match, params }) => { // <-- match undefined
const { name } = useParams();
return (
<div>
Details {match.params.name} // <-- Oops, can't read params of undefined
</div>
);
};
Remove the props and access the values returned from the useParams hook.
import React from 'react';
import { useParams } from 'react-router-dom';
export const Details = () => {
const { name } = useParams();
return (
<div>
Details {name}
</div>
);
};
The target path is also malformed. The code navigate('/country/${c.name}') is navigating to the string literal "/country/${c.name}", which is likely not what you meant to do. Fix this to use a string template literal instead to inject the c.name value into the target path.
navigate(`/country/${c.name}`) // note the backticks instead of single quotes
I oftentimes find it useful/helpful to use the generatePath utility function to create path values.
Example:
import { generatePath, useNavigate } from 'react-router-dom';
...
const path = generatePath("/country/:name", { name: c.name });
navigate(path);

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')

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.

React Native Net Info it works once

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>
);
}

React useContext returns default values

I'm trying to create a darkmode library (named react-goodnight) based on https://github.com/luisgserrano/react-dark-mode.
This is where the context is created.
import React from 'react'
const ThemeContext = React.createContext({
theme: '',
toggle: () => {}
})
export default ThemeContext
This is my useDarkMode hook that get/sets the theme to localStorage.
import { useState, useEffect } from 'react'
const useDarkMode = () => {
const [theme, setTheme] = useState('light')
const setMode = (mode) => {
window.localStorage.setItem('theme', mode)
setTheme(mode)
}
const toggle = () => (theme === 'light' ? setMode('dark') : setMode('light'))
useEffect(() => {
const localTheme = window.localStorage.getItem('theme')
localTheme && setTheme(localTheme)
}, [])
return [theme, toggle]
}
export default useDarkMode
This is the index of my library (react-goodnight).
import React, { useContext } from 'react'
import { ThemeProvider } from 'styled-components'
import { GlobalStyles } from './globalStyles'
import { lightTheme, darkTheme } from './settings'
import ThemeContext from './themeContext'
import useDarkMode from './useDarkMode'
const Provider = ({ children }) => {
const [theme, toggle] = useDarkMode()
return (
<ThemeProvider theme={theme === 'light' ? lightTheme : darkTheme}>
<GlobalStyles />
<ThemeContext.Provider value={{ theme, toggle }}>
<button onClick={toggle}>Toggle</button>
{children}
</ThemeContext.Provider>
</ThemeProvider>
)
}
export const useDarkModeContext = () => useContext(ThemeContext)
export default Provider
And, in the end, this is my example app where I'm trying to use it.
import React from 'react'
import Provider, { useDarkModeContext } from 'react-goodnight'
const App = () => {
const { theme, toggle } = useDarkModeContext();
console.log(theme)
return (
<Provider>
<div>hey</div>
<button onClick={toggle}>Toggle</button>
</Provider>
)
}
export default App
The "Toggle" button in the library's index works fine but the one in my example app does not.
The useDarkModeContext() returns empty.
What could be the issue?
Thanks!
You are doing wrong
1st option
you can use react-goodnight provider with your index.js and use useDarkModeContext(), don't name your index.js Provider else you can not use Provider coming from react-goodnight
import Provider, { useDarkModeContext } from 'react-goodnight'
const Provider = ({ children }) => {
const [theme, toggle] = useDarkMode()
return (
<ThemeProvider theme={theme === 'light' ? lightTheme : darkTheme}>
<GlobalStyles />
<Provider>
<ThemeContext.Provider value={{ theme, toggle }}>
<button onClick={toggle}>Toggle</button>
{children}
</ThemeContext.Provider>
</Provider>
</ThemeProvider>
)
}
2nd Option
you are passing ThemeContext in your index.js so you can also access that in app.js
import React, { useContext } from 'react'
import ThemeContext from './themeContext'
const App = () => {
const theme = useContext(ThemeContext);
console.log(theme)
return (
<Provider>
<div>hey</div>
<button onClick={toggle}>Toggle</button>
</Provider>
)
}
export default App
The reason it's not working is because you are calling useContext in the very same place where you print Provider.
Why is that wrong? Because useContext looks for parent context providers. By rendering Provider in the same place you call useContext, there is no parent to look for. The useContext in your example is actually part of App component, who is not a child of Provider.
All you have to do is move the button outside of that print, to its own component, and only there do useContext (or in your case the method called useDarkModeContext.
The only change would be:
import React from 'react'
import Provider, { useDarkModeContext } from 'react-goodnight'
const App = () => {
return (
<Provider>
<div>hey</div>
<ToggleThemeButton />
</Provider>
)
}
export default App
const ToggleThemeButton = () => {
const { theme, toggle } = useDarkModeContext();
return (
<button onClick={toggle}>Switch Theme outside</button>
);
};

Categories

Resources