ThemeProvider: "theme' props is required - React Native [closed] - javascript

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 22 days ago.
Improve this question
When I run my app on an android emulator I got this error:
Here is my code:
App.js:
import { StatusBar as ExpoStatusBar } from "expo-status-bar";
import React from "react";
import { ThemeProvider } from "styled-components/native";
import { theme } from "./src/infrastructure/theme";
import { RestaurantsScreen } from "./src/features/restaurants/screens/restaurants.screen";
export default function App() {
return (
<>
<ThemeProvider theme={theme}>
<RestaurantsScreen />
</ThemeProvider>
<ExpoStatusBar style="auto" />
</>
);
}
restaurant-info-card.component.js:
import React from "react";
import styled from "styled-components/native";
import { Text, StyleSheet } from "react-native";
import { Card } from "react-native-paper";
const RestaurantCard = styled(Card)`
background-color: ${(props) => props.theme.colors.bg.primary};
`;
const RestaurantCardCover = styled(Card.Cover)`
padding: ${(props) => props.theme.space[3]};
background-color: ${(props) => props.theme.colors.bg.primary};
`;
const Title = styled(Text)`
padding: ${(props) => props.theme.space[3]};
color: ${(props) => props.theme.colors.ui.primary};
`;
export const RestaurantInfoCard = ({ restaurant = {} }) => {
const {
name = "Some Restaurant",
icon,
photos = [
"https://www.foodiesfeed.com/wp-content/uploads/2019/06/top-view-for-box-of-2-burgers-home-made-600x899.jpg",
],
address = "100 some random street",
isOpenNow = true,
rating = 4,
isClosedTemporarily,
} = restaurant;
return (
<RestaurantCard elevation={5}>
<RestaurantCardCover key={name} source={{ uri: photos[0] }} />
<Title>{name}</Title>
</RestaurantCard>
);
};
restaurant.screen.js
import React from "react";
import { Searchbar } from "react-native-paper";
import { StatusBar, StyleSheet, SafeAreaView, Text, View } from "react-native";
import styled from "styled-components/native";
import { RestaurantInfoCard } from "../components/restaurant-info-card.component";
const SafeArea = styled(SafeAreaView)`
flex: 1;
margin-top: ${StatusBar.currentHeight}px;
`;
const SearchContainer = styled.View`
padding: ${(props) => props.theme.space[3]};
`;
const RestaurantListContainer = styled.View`
flex: 1;
padding: ${(props) => props.theme.space[3]};
`;
export const RestaurantsScreen = () => (
<SafeArea>
<SearchContainer>
<Searchbar />
</SearchContainer>
<RestaurantListContainer>
<RestaurantInfoCard />
</RestaurantListContainer>
</SafeArea>
);
can someone help me please this error is stuck with me. I learn this from a course on Udemy and this keeps me in the lecture and can't go further.
This is just some random text to make it meet the requirement:
af;ljadslfjiemlcjialkjlfjaiel fa;slkdfjiem fal;skjfioelajd fl;akjdf kljepidf asdl;fmas dk;fljei fla;dfkjal;sdfjla;sdjf;al meiladlj;alksdjfal;ksdjfa;dfadf;j ad;lfja df lajdfa;ldfkj adl;fkj adl;fjka dls;fjkeimlcjal;mcljeio3em3ljlk3jlkj3lkj3lkji3mm3jdj

Your issue was that
import { theme } from "./src/infrastructure/theme";
Should have been
import { theme } from "./src/infrastructure/theme/index";
In typescript if you try to import a folder it will by default look for the index file. Maybe with some babel config you could get regular javascript to do this, but I dont think it is supported out of the box. Next, you need to configure the index file:
import colors from './colors';
import { fonts, fontSizes, fontWeights } from './fonts';
import sizes from './sizes';
import { lineHeights, space } from './spacing';
export const theme = {
colors,
space,
lineHeights,
sizes,
fonts,
fontSizes,
fontWeights,
};
Demo

Related

how to type props for text area react typescript

I have a react component that looks like this:
import { TextareaHTMLAttributes} from 'react'
import styled from 'styled-components'
const TextAreaElement = styled.textarea`
border-radius: 40px;
border: none;
background: white;
`
const TextArea = (props: TextareaHTMLAttributes<any>) => { <--- replace <any> here
return <TextAreaElement {...props} />
}
I know I can do something like this, but would rather not have to add every prop manually:
const TextArea = ({placeholder} : {placeholder: string}) => {
return <TextAreaElement placeholder={placeholder} />
}
You can pass the props as regular HTML element
import React from "react";
const CustomTA = (props: React.HTMLProps<HTMLTextAreaElement>) => {
return <textarea {...props} />;
};

how to change value of react Context from another component React

so i'm trying to implement a simple theme switch via react context, and i need to change the value of context(in ThemeProvider.jsx) provider according to a onChange event in another component(ThemeSwitcher.jsx).
ThemeProvider.jsx :
import React, {createContext} from "react";
import {THEME_TYPE} from "../constants";
export const ThemeContext = createContext(THEME_TYPE.LIGHT);
const ThemeProvider = ({ children }) => {
return <>
<ThemeContext.Provider value={//THEME_TYPE.LIGHT or THEME_TYPE.DARK)}>
{children}
</ThemeContext.Provider>
</>
};
export default ThemeProvider;
ThemeSwitcher.jsx :
import React, {useContext} from "react";
import { THEME_TYPE } from "../constants";
import {ThemeContext} from "../providers/ThemeProvider";
const ThemeSwitcher = () => {
const themeMode = useContext(ThemeContext);
const handleThemeChange = (e) => {
//value of context should change according to argument 'e'
};
return (
<div className="switch-container">
<label className="switch">
<input
data-testid="theme-changer"
type="checkbox"
checked={themeMode === THEME_TYPE.DARK}
onChange={handleThemeChange}
/>
<span className="slider round"></span>
</label>
<span className="text-color bold">Dark mode</span>
</div>
);
};
export default ThemeSwitcher;
App.jsx:
import React, {useContext} from "react";
import { Helmet } from "react-helmet";
import NameBox from "./components/NameBox";
import ThemeSwitcher from "./components/ThemeSwitcher";
import { THEME_TYPE } from "./constants";
import Styles from "./data/Styles";
import ThemeProvider from "./providers/ThemeProvider";
import {ThemeContext} from "./providers/ThemeProvider";
const StyleTag = () => {
const themeMode = useContext(ThemeContext);
return (
<Helmet>
<style>{Styles(themeMode)}</style>
</Helmet>
);
};
function App() {
return (
<ThemeProvider>
<StyleTag />
<NameBox />
<ThemeSwitcher />
</ThemeProvider>
);
}
export default App;
and styles.js if necessary:
import { THEME_TYPE } from "../constants";
const Theme = {
[THEME_TYPE.LIGHT]: {
background: "#fafafa",
text: "#rgba(0, 0, 0, 0.87)",
divider: "rgba(0, 0, 0, 0.12)",
},
[THEME_TYPE.DARK]: {
background: "#303030",
text: "#fff",
divider: "rgba(255, 255, 255, 0.12)",
},
};
const Styles = (theme) => `
body {background-color: ${Theme[theme].background};}
.text-color {color: ${Theme[theme].text};}
.box {border: 1px solid ${Theme[theme].divider}}
`;
export default Styles;
as you see the value of context should be changed according to input onChange event. i couldn't come up with proper solution for relating these two, so your help is appreciated.
I suggest adding useState() hook inside ThemeProvider component.
Here is the codesandbox: https://codesandbox.io/s/magical-franklin-cril0?file=/src/ThemeProvider.jsx
That is how the code looks like:
import React, { createContext, useState } from "react";
import { THEME_TYPE } from "./constants";
export const ThemeContext = createContext(THEME_TYPE.LIGHT);
const ThemeProvider = ({ children }) => {
const [themeType, setThemeType] = useState(THEME_TYPE.LIGHT);
const changeTheme = (value) => {
if (value) {
setThemeType(THEME_TYPE.DARK);
} else {
setThemeType(THEME_TYPE.LIGHT);
}
};
return (
<>
<ThemeContext.Provider value={{ themeType, changeTheme }}>
{children}
</ThemeContext.Provider>
</>
);
};
export default ThemeProvider;
And then you would use the context where needed like this:
const themeMode = useContext(ThemeContext)
themeMode.themeType // THEME_TYPE.LIGHT or THEME_TYPE.DARK
themeMode.changeTheme(value) // if value is true, it would change to dark mode, if false to light mode

How to use const of one component in another component

I'm new to reactjs. I'm trying to implement a toggleTheme action in every page of my project.
So, Instead of declaring it in every component, I thought of creating a toggle theme component itself and import it in all other components.
I don't know why but for some reason it is not working properly.
Here is my code...
toggletheme.js
import Brightness4Icon from '#material-ui/icons/Brightness4';
import Brightness7Icon from '#material-ui/icons/Brightness7';
import React, { useState } from 'react';
import './BasePage.css';
const ToggleTheme = (isLight, setLight) => {
[isLight, setLight] = useState("true");
const toggleTheme = () => {
setLight(!isLight);
}
console.log(isLight)
return (
<div className="themebtn" onClick={toggleTheme}>
{isLight ? <Brightness7Icon /> : <Brightness4Icon />}
</div>
)
}
export default ToggleTheme
Another component in which I want to import toggletheme component basepage.js
import ToggleTheme from './ToggleTheme'
import React, { useState } from 'react';
const Basepage = () => {
return (
<div className={isLight ? "light" : "dark"}>
<div>
<ToggleTheme />
</div>
</div>
)
}
export default Basepage
basepage.css
.light {
--background: #ffffff;
--background-color: #f1f1f1;
--blue: #1b98f5;
--foreground: #323234;
--shadow: 4px 4px 4px #aaa;
}
.dark {
--background: #323234;
--background-color: #202124;
--blue: #1b98f5;
--foreground: #f1f1f1;
--shadow: 4px 4px 4px #222;
}
I'm getting at isLight in my basepage.js
I would appreciate some help in rectifying it.
Thank you.
It is very simple, because you are using a string "true" to set the initial state of the variable in your file toggletheme.js and remember that a string with characters is always true, that is why in the ternary operator you asked if the variable was true or not, and it returns always true.
Just change this useState("true") to useState(true).
import Brightness4Icon from '#material-ui/icons/Brightness4';
import Brightness7Icon from '#material-ui/icons/Brightness7';
import React, { useState } from 'react';
import './BasePage.css';
const ToggleTheme = (isLight, setLight) => {
[isLight, setLight] = useState(true);
const toggleTheme = () => {
setLight(!isLight);
}
console.log(isLight)
return (
<div className="themebtn" onClick={toggleTheme}>
{isLight ? <Brightness7Icon /> : <Brightness4Icon />}
</div>
)
}
export default ToggleTheme
const ToggleTheme = ({isLight, setLight}) => {
const toggleTheme = () => {
setLight(!isLight);
}
console.log(isLight)
return (
<div className="themebtn" onClick={toggleTheme}>
{isLight ? <Brightness7Icon /> : <Brightness4Icon />}
</div>
)
}
const Basepage = () => {
const [isLight, setLight] = React.useState(true);
return (
<div className={isLight ? "light" : "dark"}>
<div>
<ToggleTheme isLight={isLight} setLight={setLight} />
</div>
</div>
)
}
I have majorly used chakra-ui and I have hated the fact that you can use true and false to set the theme, what if you choose to have a different theme down the road ?
import Brightness4Icon from '#material-ui/icons/Brightness4';
import Brightness7Icon from '#material-ui/icons/Brightness7';
import { useEffect, useState } from 'react';
const useTheme = () => {
let themes=['light','dark'];
let icons =[ <Brightness7Icon /> , <Brightness4Icon />]
const [icon,setIcon]=useState(<Brightness7Icon />);
let [theme, setTheme] = useState("light");
let changeTheme=()=>{
let index =themes.indexOf(theme)
if(index==themes.length-1)
{
setTheme(themes[0]);
setIcon(icons[0]);
}
else{
setTheme(themes[index+1]);
setIcon(icons[index+1]);
}
}
useEffect(()=>{
},[theme])
return ([theme,changeTheme,<div onClick={changeTheme}>{icon}</div>])
}
export default useTheme
import useTheme from './toggle'
import React from 'react';
const Basepage = () => {
let [theme,changeTheme,icon] = useTheme();
return (
<div className={theme}>
<div>
{icon}
</div>
</div>
)
}
export default Basepage

What will be the Unit / Component / Snapshot test in Jest for Below code Sample for React Native app

I am learning jest and writing component test cases for React Native App, can anyone suggest what all possible test's component test, unit, snapshot test I can write for the code below with the code snippet:
import React, { Component } from 'react';
import { View } from 'react-native';
import { Colors } from '../../themes';
export default class Divider extends Component {
render() {
const { style } = this.props;
return (
<View style={[
{
flex: 1,
height: 1,
backgroundColor: Colors.divider,
marginVertical: 8,
}, style]} />
);
}
}
Also, suggest if the below test case I have written is good or valid:
import TestRenderer from 'react-test-renderer';
import { View } from 'react-native';
import React from 'react';
import Divider from '../Divider';
test('should test on Divider props', () => {
const testRenderer = TestRenderer.create(
<Divider style={{ height: 10 }} />);
const testInstance = testRenderer.root;
const dividerView = testInstance.findByType(View).props.style[1];
expect(dividerView.height).toBe(10);
});

Using ThemeProvider props in Global Styled-Components

How can I access the ThemeProvider props in global.js when using styled-components?
For example in theme.js I have ${props => props.theme.fonts.fontSize} calling a default font size of 16px
const theme = {
fonts: {
fontSize : '16px',
}
}
export default theme
This is provided in /layouts/index.js as
import React from 'react'
import { ThemeProvider } from 'styled-components'
import '../style/global';
import theme from '../style/theme'
class Template extends React.Component {
render() {
const { children } = this.props
return (
<ThemeProvider theme={theme}>
...
{children()}
...
</ThemeProvider>
)
}
}
export default Template
From here I can access the ${props => props.theme.fonts.fontSize} within each component or child page.
But how can I pass to global.js in the same way when global is technically a level above theme.js? So that I could create a global style as
injectGlobal`
html {
font-size: (${props => props.theme.fonts.fontSize} / 16px) * 1em;
}
`
The easiest way off solving this is by creating a top level component that injects your desired styling like this:
import { Children } from 'react';
import { withTheme, injectGlobal } from 'styled-components';
const GlobalComponent = ({ theme, children }) => {
injectGlobal`
font-size: ${theme.fonts.fontSize}
}
`;
return Children.only(children);
};
export default withTheme(Global);
This will make sure all Components that have this Component as a parent will have the desired globalStyling. Hope this helped
Late but now we can actually create a Global Component and pass it as a child of ThemeProvider. It will allow you to access all the props of current theme.
Example for applying font family:
Your Global.js / Global.ts
import { createGlobalStyle } from "styled-components";
const GlobalStyle = createGlobalStyle`
html,
body {
padding: 0;
margin: 0;
font-family: ${(props) => props.theme.font.family}
}
a {
color: inherit;
text-decoration: none;
}
* {
box-sizing: border-box;
}
`;
export default GlobalStyle;
Your Main component app.tsx / app.jsx
import theme...
import { ThemeProvider } ...
imort GlobalStyle from '../path-to-global-file';
const App ...
.
.
return(
<>
<ThemeProvider theme={theme}>
<GlobalStyle />
{ /* Root component */ }
<Component/>
</ThemeProvider>
</>
);
You can use the props easily now.

Categories

Resources