Can someone help me understand the correct syntax for allowing a dynamic theme object to be imported from a separate file?
I am trying to get the system theme from a media query and then set the theme dynamically.
This works fine if I leave everything all in the main App function like this:
https://stackblitz.com/edit/theme-builder-working-all-in-one?file=index.js
But I want to have it broken up into different files for organization in the example below but my attempt is broken, I get the error: themeProvider_js_1.default is not a function
broken example:
https://stackblitz.com/edit/theme-builder-broken?file=index.js
This is a second try of refactoring, no errors, I can see the ThemeObject existing in the console log but the system theme isn't being applied:
https://stackblitz.com/edit/theme-builder-broken-btyufg?file=index.js
Code for the future:
working code, but I want to refactor this so the theme and media query objects are outside of the App component:
import React from 'react';
import { render } from 'react-dom';
import useMediaQuery from '#material-ui/core/useMediaQuery';
import { createMuiTheme, ThemeProvider } from '#material-ui/core/styles';
import CssBaseline from '#material-ui/core/CssBaseline';
function App() {
const prefersDarkMode = useMediaQuery('(prefers-color-scheme)');
const theme = React.useMemo(
() =>
createMuiTheme({
palette: {
type: prefersDarkMode ? 'dark' : 'light',
},
}),
[prefersDarkMode],
);
return (
<ThemeProvider theme={theme}>
<CssBaseline/>
<p>
Start editing to see some magic happen :)
</p>
</ThemeProvider>
);
}
render(<App />, document.getElementById('root'));
broken refactor attempt:
App component
import React from 'react';
import { render } from 'react-dom';
import useMediaQuery from '#material-ui/core/useMediaQuery';
import { createMuiTheme, ThemeProvider } from '#material-ui/core/styles';
import themeBuilder from './themeProvider.js'
function App() {
return (
<ThemeProvider theme={themeBuilder()}>
<p>
Start editing to see some magic happen :)
</p>
</ThemeProvider>
);
}
render(<App />, document.getElementById('root'));
themeBuilder
import React from 'react';
import { createMuiTheme } from '#material-ui/core/styles';
import useMediaQuery from '#material-ui/core/useMediaQuery';
function themeBuilder() {
const prefersDarkMode = useMediaQuery('(prefers-color-scheme)');
const theme = React.useMemo(
() =>
createMuiTheme({
palette: {
type: prefersDarkMode ? 'dark' : 'light',
},
}),
[prefersDarkMode],
);
return theme
}
I think you're missing export default in themeProvider.js
export default function themeBuilder() {
const prefersDarkMode = useMediaQuery('(prefers-color-scheme)');
const theme = React.useMemo(
() =>
createMuiTheme({
palette: {
type: prefersDarkMode ? 'dark' : 'light',
},
}),
[prefersDarkMode],
);
return theme
}
Related
I was trying to react query for the first time then I got this at the start of my React app.
import React from 'react'
import { useQuery } from "react-query";
const fetchPanets = async () => {
const result = await fetch('https://swapi.dev/api/people')
return result.json()
}
const Planets = () => {
const { data, status } = useQuery('Planets', fetchPanets)
console.log("data", data, "status", status)
return (
<div>
<h2>Planets</h2>
</div>
)
}
export default Planets
As the error suggests, you need to wrap your application in a QueryClientProvider. This is on the first page of the docs:
import { QueryClient, QueryClientProvider, useQuery } from 'react-query'
const queryClient = new QueryClient()
export default function App() {
return (
<QueryClientProvider client={queryClient}>
<Example />
</QueryClientProvider>
)
}
While this is most commonly caused by not having your application wrapped in a <QueryClientProvider>, in my case it happened because I was importing some shared components, which ended up with a different context. You can fix this by setting the contextSharing option to true
That would look like:
import { QueryClient, QueryClientProvider } from 'react-query'
const queryClient = new QueryClient()
function App() {
return <QueryClientProvider client={queryClient} contextSharing={true}>...</QueryClientProvider>
}
From the docs: (https://react-query.tanstack.com/reference/QueryClientProvider)
contextSharing: boolean (defaults to false)
Set this to true to enable context sharing, which will share the first and at least one instance of the context across the window to ensure that if React Query is used across different bundles or microfrontends they will all use the same instance of context, regardless of module scoping.
Just make changes like below it will work fine
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import { QueryClient, QueryClientProvider } from "react-query";
const queryClient = new QueryClient();
ReactDOM.render(
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>,
document.getElementById('root')
);
import { QueryClient, QueryClientProvider, useQuery } from 'react-query';
const queryClient = new QueryClient();
const fetchPanets = async () => {
const result = await fetch('https://swapi.dev/api/people')
return result.json()
}
const Planets = () => {
const { data, status } = useQuery('Planets', fetchPanets)
console.log("data", data, "status", status)
return (
<div>
<h2>Planets</h2>
</div>
);
}
export default function Wraped(){
return(<QueryClientProvider client={queryClient}>
<Planets/>
</QueryClientProvider>
);
}
Single SPA (micro-frontend) - React Query v3.34.15
I was getting this error while trying to integrate a sigle-spa react parcel into the root application.
I used craco-plugin-single-spa-application for the building of a CRA app as a way to adapt it for a parcel. In the entry config I was pointing to my single-spa-react config.
// craco.config.js
const singleSpaApplicationPlugin = require('craco-plugin-single-spa-application')
module.exports = {
plugins: [
{
plugin: singleSpaApplicationPlugin,
options: {
orgName: 'uh-platform',
projectName: 'hosting',
entry: 'src/config/single-spa-index.cf.js',
orgPackagesAsExternal: false,
reactPackagesAsExternal: true,
externals: [],
minimize: false
}
}
]
}
In the single-spa-index.cf.js file I had the following configs.
import React from 'react'
import ReactDOM from 'react-dom'
import singleSpaReact from 'single-spa-react'
import App from '../App'
const lifecycles = singleSpaReact({
React,
ReactDOM,
rootComponent: App,
errorBoundary() {
return <div>Ocorreu um erro desconhecido!</div>
}
})
export const { bootstrap, mount, unmount } = lifecycles
After reading a bunch of forums and the react-query documentation, the only thing that I figured out I needed to change was pass in the QueryClientProvider the prop contextSharing as true. After had did this change, ran the building and access the route that opens my parcel. I got the same error.
import React from 'react'
import ReactDOM from 'react-dom'
import { QueryClient, QueryClientProvider } from 'react-query'
import { ReactQueryDevtools } from 'react-query/devtools'
import App from './App'
const queryClient = new QueryClient()
const isDevelopmentEnv = process.env.NODE_ENV === 'development'
if (isDevelopmentEnv) {
import('./config/msw/worker').then(({ worker }) => worker.start())
}
ReactDOM.render(
<React.StrictMode>
<QueryClientProvider contextSharing={true} client={queryClient}>
<App />
{isDevelopmentEnv && <ReactQueryDevtools initialIsOpen={false} />}
</QueryClientProvider>
</React.StrictMode>,
document.getElementById('root')
)
But, how do I solved that. Well, it was was simple. I couldn't even imagine why it was working locally. But not after building and integration.
The problem was because I put the React Query Provider inside the index o the application and in my single-spa-index.cf.js I was importing import App from '../App' which really wasn't wrapped by the provider. Once I also was importing App in the application index, where It was wrapped making It works locally. 😢😢
So after figure that out, my code was like that:
CODE AFTER SOLUTION
// craco.config.js
const singleSpaApplicationPlugin = require('craco-plugin-single-spa-application')
module.exports = {
plugins: [
{
plugin: singleSpaApplicationPlugin,
options: {
orgName: 'uh-platform',
projectName: 'hosting',
entry: 'src/config/single-spa-index.cf.js',
orgPackagesAsExternal: false,
reactPackagesAsExternal: true,
externals: [],
minimize: false
}
}
]
}
// src/config/single-spa-index.cf.js
import React from 'react'
import ReactDOM from 'react-dom'
import singleSpaReact from 'single-spa-react'
import App from '../App'
const lifecycles = singleSpaReact({
React,
ReactDOM,
rootComponent: App,
errorBoundary() {
return <div>Ocorreu um erro desconhecido!</div>
}
})
export const { bootstrap, mount, unmount } = lifecycles
// App.tsx
import { QueryClient, QueryClientProvider } from 'react-query'
import { ReactQueryDevtools } from 'react-query/devtools'
import { config } from 'config/react-query'
import Routes from 'routes'
import GlobalStyles from 'styles/global'
import * as S from './styles/shared'
const queryClient = new QueryClient(config)
const isDevelopmentEnv = process.env.NODE_ENV === 'development'
if (isDevelopmentEnv) {
import('./config/msw/worker').then(({ worker }) => worker.start())
}
function App() {
return (
<QueryClientProvider contextSharing={true} client={queryClient}>
<S.PanelWrapper>
<Routes />
<GlobalStyles />
</S.PanelWrapper>
<ReactQueryDevtools initialIsOpen={false} />
</QueryClientProvider>
)
}
export default App
// index.tsx
import { StrictMode } from 'react'
import ReactDOM from 'react-dom'
import App from './App'
ReactDOM.render(
<StrictMode>
<App />
</StrictMode>,
document.getElementById('root')
)
Well, it was long but I hope it helps someone that's undergoing for the same problem as mine. 🙌🙌🙌
I was trying to fix the same thing:
I followed the React Query docs
and used the concept of Higher Order Component
See if it helps:
import React from 'react';
import { QueryClient, QueryClientProvider, useQuery } from 'react-query';
import Planet from './Planet';
const queryClient = new QueryClient();
const fetchPlanets = async () => {
const res = await fetch('http://swapi.dev/api/planets/');
return res.json();
}
const Planets = () => {
const { data, status } = useQuery('planets', fetchPlanets);
return (
<div>
<h2>Planets</h2>
{ status === 'loading' && (<div>Loading data...</div>)}
{ status === 'error' && (<div>Error fetching data</div>)}
{
status === 'success' && (
data.results.map(planet =>
<Planet
key={planet.name}
planet={planet}
/>
)
)
}
</div>
)
}
// Higher order function
const hof = (WrappedComponent) => {
// Its job is to return a react component warpping the baby component
return (props) => (
<QueryClientProvider client={queryClient}>
<WrappedComponent {...props} />
</QueryClientProvider>
);
};
export default hof(Planets);
In my case I was importtng from 'react-query' in one place and '#tanstack/react-query' in another.
I got that error when trying to add the react-query devtools.
The problem was I was installing it wrongly according my version, I was using react-query v3.
WRONG FOR react-query V3 (GOOD FOR V4)
import { ReactQueryDevtools } from '#tanstack/react-query-devtools';
OK FOR react-query V3
import { ReactQueryDevtools } from 'react-query/devtools';
In my case I accidentally used two different versions of react-query in my modules.
In my case
Error import { QueryClient, QueryClientProvider } from "#tanstack/react-query";
Solution import { QueryClient, QueryClientProvider } from "react-query";
remove it #tanstack/
Just be careful when upgrade from react-query v3 to #tanstack/react-query v4.
Ensure that you replace all imports as "react-query" to "#tanstack/react-query" and then run yarn remove the lib that you won't use anymore, otherwise you may accidentally import the unexpected one.
This happened to me and caused this error.
I'm wondering if there is a way to access theme.customElements.acitonButton in MyComponent without having to use makeStyles? For example, can I somehow enter className={theme.customElements.actionButton}?
theme.js
const theme = createMuiTheme({
customElements: {
actionButton: {
backgroundColor: '#007AFF'
}
}
})
export default theme
MyComponent.tsx
import { makeStyles, createStyles, Theme } from '#material-ui/core'
// wondering if i can remove makeStyles and somehow access styles set in theme.js and add to <IconButton />?
const useStyles: any = makeStyles((theme: Theme) => {
return createStyles({
actionButton: theme.customElements.actionButton
})
})
const MyComponent: React.FunctionComponent<MyComponentProps> = props => {
const classes = useStyles()
<IconButton className={classes.actionButton} />
}
You can override the style of a Component or Element in the theme.
To do that, you need to create the a folder called overrides in theme folder and create a file with the same name as the component whose theme you want to override.
Then you can change the component style like this.
export default {
elevation1: {
boxShadow: '0 0 0 1px rgba(63,63,68,0.05), 0 1px 3px 0 rgba(63,63,68,0.15)'
}
};
Also you need to add the theme provider to App.js.
import React from 'react';
import ThemeProvider from '#material-ui/styles/ThemeProvider';
import CssBaseline from '#material-ui/core/CssBaseline';
import {darkBlueTheme} from './theme';
import Routes from './Routes';
function App() {
return (
<StateProvider reducer={appReducer} initialState={getInitialState()}>
<ThemeProvider theme={darkBlueTheme}>
App CODE HERE
</ThemeProvider>
</StateProvider>
);
}
export default App;
I have a site built with React Static that has a Header component that is always present. Depending on if the current page has a hero component or not, the Header should be either light or dark.
The Header is rendered outside of the routes and the useEffect is triggered before the children is rendered. This is probably because of the routing.
This is the current code:
// App.js
import React, { useState, useEffect } from 'react'
import { Root, Routes } from 'react-static'
export default () => {
const [useDarkTheme, setUseDarkTheme] = useState(false);
useEffect(() => {
if (typeof document !== "undefined") {
const heroPresent = document.querySelectorAll(".o-hero").length > 0;
console.log("The hero is present: " + heroPresent);
setUseDarkTheme(!heroPresent);
}
})
return (
<Root>
<React.Suspense fallback={ <em>Loading...</em> }>
<Header useDarkTheme={ useDarkTheme } />
<Routes default />
</React.Suspense>
</Root>
);
}
What will be rendered at <Routes default /> is the static pages configured in React Static's static.config.js.
Below is an example of the Hero component:
// Hero.js
import React from "react";
export default () => {
console.log("This is the Hero rendering. If this exist, the Header should be dark.");
return (
<div className="o-hero">
<p>Hero!</p>
</div>
);
}
When I run the application and look at the logs this is what I get:
The hero is present: false
This is the Hero rendering. If this exist, the Header should be dark.
How could I somehow detect the presence of the Hero from the Header although the Hero is in a router and the Header is not? This feels like quite a common use case, but I could not find any info on the interwebs.
Thanks in advance!
So I ended up using useContext to provide all children with a getter and a setter for the Header's theme (dark or light). The solution is very much inspired from this answer. The solution looks like this:
// App.js
import React, { useState, useContext } from 'react'
import { Root, Routes } from 'react-static'
import { HeaderThemeContext } from "./context";
export default () => {
const { theme } = useContext(HeaderThemeContext);
const [headerTheme, setHeaderTheme] = useState(theme);
return (
<Root>
<React.Suspense fallback={ <em>Loading...</em> }>
<HeaderThemeContext.Provider value={ { theme: headerTheme, setTheme: setHeaderTheme } }>
<Header theme={ headerTheme } />
<Routes default />
</HeaderThemeContext.Provider>
</React.Suspense>
</Root>
);
}
// Hero.js
import React from "react";
import { headerThemes, setHeaderTheme } from "./context";
export default () => {
setHeaderTheme(headerThemes.DARK);
console.log("This is the Hero rendering. If this exist, the Header should be dark.");
return (
<div className="o-hero">
<p>Hero!</p>
</div>
);
}
// context.js
import React, { createContext, useContext } from "react";
export const headerThemes = {
LIGHT: "light",
DARK: "dark",
};
export const HeaderThemeContext = createContext({
theme: headerThemes.LIGHT,
setTheme: () => {}
});
// This is a hook and can only be used in a functional component with access to the HeaderThemeContext.
export const setHeaderTheme = theme => useContext(HeaderThemeContext).setTheme(theme);
This gives global access to set and get the header theme, which might not be optional, but it works for now and I think it's fine. Please let me know if there is a better way of doing this.
I don't know my issue is a bug or just a support term or just a configuration mismach, but I spend much time, Not happy go lucky writing here to somebody settle my issue. no!
I searched for 3 days, Even just sleep about 10 hours in this 3 days, try many ways, even I use Gitter but no one answer me, I see issues #10982 and #11506 and many Stack Overflow question and answers but I couldn't fix my issue and didn't find right way.
Absolutely I read and read many times the Material-UI Docs but I exactly did what the Docs said.
At last, I see class name hydration mismatch in server and client, 😞 this warning:
Warning: Prop `className` did not match. Server: "MuiFormLabel-root-134 MuiInputLabel-root-129 MuiInputLabel-formControl-130 MuiInputLabel-animated-133" Client: "MuiFormLabel-root-10 MuiInputLabel-root-5 MuiInputLabel-formControl-6 MuiInputLabel-animated-9"
I swear I tried many ways and searched a lot. I'm using Material-UI version 1.2.1.
This is my Index component as a root component:
import React, {Component} from 'react';
import Helmet from 'react-helmet';
import styles from 'StylesRoot/styles.pcss';
import TextField from '#material-ui/core/TextField';
export default class App extends Component {
render() {
return (
<div className={styles['root-wrapper']}>
<Helmet
htmlAttributes={{lang: 'fa', amp: undefined}}
bodyAttributes={{dir: 'rtl'}}
titleTemplate='اسکن - %s'
titleAttributes={{itemprop: 'name', lang: 'fa'}}
meta={[
{name: 'description', content: 'صفحه اتصال اعضاء'},
{name: 'viewport', content: 'width=device-width, initial-scale=1'},
]}
link={[{rel: 'stylesheet', href: '/dist/styles.css'}]}
/>
<TextField label='test' helperText='help'/>
</div>
);
};
}
Here below you can see my server.jsx and client.jsx:
//--------------------------------------------client.jsx
import React from 'react';
import {hydrate} from 'react-dom';
import {BrowserRouter} from 'react-router-dom';
import {MuiThemeProvider, createMuiTheme} from '#material-ui/core/styles';
import {lightBlue, red} from '#material-ui/core/colors';
import Index from './app/index';
import RTL from './app/public/rtl';
const theme = createMuiTheme({
palette: {
primary: lightBlue,
accent: red,
type: 'light',
},
direction: 'rtl',
});
class Main extends React.Component {
// Remove the server-side injected CSS.
componentDidMount() {
const jssStyles = document.getElementById('jss-server-side');
if (jssStyles && jssStyles.parentNode) {
jssStyles.parentNode.removeChild(jssStyles);
}
}
render() {
return (
<BrowserRouter>
<Index {...this.props}/>
</BrowserRouter>
);
}
}
hydrate((
<RTL>
<MuiThemeProvider theme={theme}>
<Main/>
</MuiThemeProvider>
</RTL>
), document.getElementById('root'));
//--------------------------------------------server.jsx
import React from 'react';
import {renderToString} from 'react-dom/server';
import {SheetsRegistry} from 'react-jss/lib/jss';
import JssProvider from 'react-jss/lib/JssProvider';
import {StaticRouter} from 'react-router-dom';
import {Helmet} from "react-helmet";
import {MuiThemeProvider, createMuiTheme, createGenerateClassName} from '#material-ui/core/styles';
import {red, lightBlue} from '#material-ui/core/colors';
import Template from './app/template';
import Index from './app/index';
import RTL from './app/public/rtl';
export default function serverRenderer({clientStats, serverStats}) {
return (req, res, next) => {
const context = {};
const sheetsRegistry = new SheetsRegistry();
const theme = createMuiTheme({
palette: {
primary: lightBlue,
accent: red,
type: 'light',
},
direction: 'rtl',
});
const generateClassName = createGenerateClassName();
const markup = renderToString(
<JssProvider registry={sheetsRegistry} generateClassName={generateClassName}>
<RTL>
<MuiThemeProvider theme={theme} sheetsManager={new Map()}>
<StaticRouter location={req.url} context={context}>
<Index/>
</StaticRouter>
</MuiThemeProvider>
</RTL>
</JssProvider>
);
const helmet = Helmet.renderStatic();
const jss = sheetsRegistry.toString();
res.status(200).send(Template({
markup: markup,
helmet: helmet,
jss: jss,
}));
};
}
So now it's needed to template.jsx:
export default ({ markup, helmet, jss }) => {
return `<!DOCTYPE html>
<html ${helmet.htmlAttributes.toString()}>
<head>
${helmet.title.toString()}
${helmet.meta.toString()}
${helmet.link.toString()}
<style id='jss-server-side'>${jss}</style>
</head>
<body ${helmet.bodyAttributes.toString()}>
<div id='root'>${markup}</div>
<script src='/dist/client.js' async></script>
</body>
</html>`;
};
Ok, Now it is possible that this question is asked What is RTL? and Why you wrap MuiThemeProvider inside it in both server and client?
So first see RTL component:
import React from 'react';
import {create} from 'jss';
import rtl from 'jss-rtl';
import JssProvider from 'react-jss/lib/JssProvider';
import {createGenerateClassName, jssPreset} from '#material-ui/core/styles';
const jss = create({plugins: [...jssPreset().plugins, rtl()]});
const generateClassName = createGenerateClassName();
export default props => (
<JssProvider jss={jss} generateClassName={generateClassName}>
{props.children}
</JssProvider>
);
I saw it in Material-UI Docs and I believe the documentation is a little poor and could be improved. I asked myself, Why documentation pass a props.children for this function? and I guess maybe this function should wrap something. so I try many shapes and it works. but in the first call in browser after build. when I refresh the browser then the warning appears 😞 and I see this damn shape:
Surely I wanna see below shape, but I see it just once after build:
I don't know what is going wrong. I leave an issue on Github too. And upload a mini repo for this issue, for seeing my issue just pull, and run npm install then num run dev. the project is accessible on localhost:4000
I don't know this way is proper or not, But it works well, Actually, I find out, using separate RTL Component, is not a good way, This cause to the inconsistency between server and client, I use the Right-to-Left Documentation page for each server and client-side separately, Hence omit the Rtl.jsx file and it's component from my project, So, server.jsx and client.jsx is like below:
//---------------------------------------------client.jsx
import React, {Component} from 'react';
import {hydrate} from 'react-dom';
import {BrowserRouter} from 'react-router-dom';
import {
MuiThemeProvider, createMuiTheme,
createGenerateClassName, jssPreset
} from '#material-ui/core/styles';
import {create} from 'jss';
import rtl from 'jss-rtl';
import JssProvider from 'react-jss/lib/JssProvider';
import {lightBlue, red} from '#material-ui/core/colors';
import Index from './app/index';
const theme = createMuiTheme({
palette: {
primary: lightBlue,
accent: red,
type: 'light',
},
direction: 'rtl',
});
const jssRTL = create({plugins: [...jssPreset().plugins, rtl()]});
const generateClassName = createGenerateClassName();
class Main extends Component {
componentDidMount() {
const jssStyles = document.getElementById('jss-server-side');
if (jssStyles) {
jssStyles.remove();
}
}
render() {
return (
<BrowserRouter>
<Index {...this.props}/>
</BrowserRouter>
);
}
}
hydrate((
<JssProvider jss={jssRTL} generateClassName={generateClassName}>
<MuiThemeProvider theme={theme}>
<Main/>
</MuiThemeProvider>
</JssProvider>
), document.getElementById('root'));
//---------------------------------------------server.jsx
import React from 'react';
import {renderToString} from 'react-dom/server';
import {SheetsRegistry} from 'react-jss/lib/jss';
import JssProvider from 'react-jss/lib/JssProvider';
import {StaticRouter} from 'react-router-dom';
import {Helmet} from "react-helmet";
import {
MuiThemeProvider, createMuiTheme,
createGenerateClassName, jssPreset
} from '#material-ui/core/styles';
import {create} from 'jss';
import rtl from 'jss-rtl';
import {red, lightBlue} from '#material-ui/core/colors';
import Template from './app/template';
import Index from './app/index';
export default function serverRenderer({clientStats, serverStats}) {
return (req, res, next) => {
const context = {};
const sheetsRegistry = new SheetsRegistry();
const theme = createMuiTheme({
palette: {
primary: lightBlue,
accent: red,
type: 'light',
},
direction: 'rtl',
});
const jssRTL = create({plugins: [...jssPreset().plugins, rtl()]});
const generateClassName = createGenerateClassName();
const markup = renderToString(
<JssProvider jss={jssRTL}
registry={sheetsRegistry}
generateClassName={generateClassName}>
<MuiThemeProvider theme={theme} sheetsManager={new Map()}>
<StaticRouter location={req.url} context={context}>
<Index pathname={req.url}/>
</StaticRouter>
</MuiThemeProvider>
</JssProvider>
);
const helmet = Helmet.renderStatic();
const jss = sheetsRegistry.toString();
res.status(200).send(Template({
markup,
helmet,
jss,
}));
};
}
It works well on both sides, server, and client and makes consistent Material-UI CSS in style tag.
My target is to have one main theme for the app and load custom vendor styles if one is set.
I have been following the tutorial of react-css-themr and I can't get it to work. The minimalistic example I could come up with is this:
my module:
import {render} from 'react-dom'
import React from 'react';
import {Item} from './components/presentational/Item';
import {ThemeProvider} from 'react-css-themr';
import style from './theme/ItemDefault.scss';
const contextTheme = {
Item: require('./theme/ItemVendor.scss'),
};
const About = () => {
return (
<ThemeProvider theme={contextTheme}>
<Item theme={style} className={style.red}/>
</ThemeProvider>
)
};
ItemDefault.scss:
.button{
color:deeppink;
}
ItemVendor.scss:
.button{
color:orangered;
}
That doesn't seem to give my any classes or any styling. Any ideas please?
The way I was wiring components was incorrect. The way to do this is as follows:
In the root component you need to have your theme provider and theme attached to it. This theme will override any child component theming.
import {render} from 'react-dom'
import React from 'react';
import {ThemeProvider} from 'react-css-themr';
import inlineCss from './page.scss';
import {Item} from './components/Item';
const contextTheme = {
Item: require('./theme/ItemVendor.scss'),
};
render((
<ThemeProvider theme={contextTheme}>
<Item />
</ThemeProvider>
), document.getElementById('app'));
The component itself will have it's default theming and then will be wrapped with themr API to overwrite the it's default settings.
import {render} from 'react-dom'
import React from 'react';
import { themr } from 'react-css-themr';
import defaultTheme from './Item.scss';
const DefaultItem = ({theme}) => {
return (
<div className={theme.button} >
Example item
</div>
)
};
export const Item = themr('Item', defaultTheme)(DefaultItem);
I put together a github repo showing how to use this:
https://github.com/adamgajzlerowicz/react-css-themr