I just started learning React but I can't for the life of me figure out how to link a new file to the App.jsx file. I've seen related questions but the setups are all quite different to mine. I used the default Vite template provided (for the most part). I've provided simple snippets of code below.
App.jsx code below:
import React from 'react'
import { useState } from 'react'
import './App.css'
import Pets from './components/Pets'
function App() {
return (
<div className="App">
<Animals/>
</div>
)
}
export default App
The page I'd like to link:
import React from 'react'
function Animals() {
return(
<div>
<h3>Pets for Africa</h3>
<ul>
<li>dogs</li>
<li>cats</li>
</ul>
</div>
)
}
export default Animals
The default main.jsx file which is part of the Vite template
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')).render(
<React.StrictMode>
<App />
</React.StrictMode>
)
Change the default import's name to Animals
import React from 'react'
import { useState } from 'react'
import './App.css'
import Animals from './components/Pets'
function App() {
return (
<div className="App">
<Animals/>
</div>
)
}
export default App
This should work in your case.
Aren't you trying to import file Pets which has name Animals? If yes, simply rename the import Pets from './components/Pets' to import Animals from './components/Animals'
I've tried to follow exactly what's documented here:
How to theme components with styled-components and Material-UI?
import React from "react";
import { withTheme } from "#material-ui/core/styles";
import styled from "styled-components";
const StyledDiv = withTheme(styled.div`
background: ${props => props.theme.palette.primary.main};
color: ${props => props.theme.palette.primary.contrastText};
`);
export default function App() {
return (
<StyledDiv>
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
</StyledDiv>
);
}
But instead of using a "standard" HTML component like above I tried against a Material-UI Button with no luck. Can someone please help me with what I am doing wrong?
This is what I am trying:
styles.ts
import styled from 'styled-components';
import { withTheme } from "#material-ui/core/styles";
import { Button } from '#material-ui/core';
export const StyledInnerSignInButton = withTheme(styled(Button)`
margin: ${props => props.theme.spacing(3, 0, 2)};
`)
index.tsx
import { StyledInnerSignInButton } from './styles';
[...]
<StyledInnerSignInButton
type="submit"
fullWidth
variant="contained"
color="primary"
>
Sign In
</StyledInnerSignInButton>
I'm stuck here and still a React newbie. Any help is greatly appreciated!
I managed to resolve my issue. It was due to specificity. There are two ways to mitigate that, one is by wrapping the new component style with &&, for example:
export const StyledInnerSignInButton = withTheme(styled(Button)`
&& { margin: ${props => props.theme.spacing(3, 0, 2)}; }
`)
Or by manipulating the CSS Injection Order, as documented here
In your "master" index.tsx file, you will set up your code this way:
import React from 'react';
import { render } from 'react-dom';
import { StylesProvider } from '#material-ui/core/styles';
import Home from './pages/Home';
render(
<React.StrictMode>
<StylesProvider injectFirst>
{/* component name */}
<Home />
</StylesProvider>
</React.StrictMode>,
document.getElementById('root')
)
I hope that helps someone with the same problem as me.
So I'm building a RubyOnRails application with React in the frontend. I have several microfrontends and I render each of them separately. Like this:
index.html.erb
<div id="app-header" />
<div id="app-content" />
Header.jsx
import React from 'react';
import styled from 'styled-components';
import ReactDOM from 'react-dom';
const StyledHeader = styled.div`
// ...
`;
const Header = () => {
return <StyledHeader>...</StyledHeader>;
}
document.addEventListener('DOMContentLoaded', () => {
ReactDOM.render(
<Header />,
document.getElementById('app-header'));
});
App.jsx.jsx
import React from 'react';
import styled from 'styled-components';
import ReactDOM from 'react-dom';
const StyledApp = styled.div`
// ...
`;
const App = () => {
return <StyledApp>...</StyledApp>;
}
document.addEventListener('DOMContentLoaded', () => {
ReactDOM.render(
<App />,
document.getElementById('app-content'));
});
The problem is that it looks like styled-components one renders the last styles from ReactDOM.render.
So in this case only app-content would be styled. If I remove it, than app-header is styled. I inspected the elements and it looks like the styles from app-header are not in the DOM when app-content is present. It's like it gets overridden.
I can't make the content and the header under the same root component because the content is not always React.
Is there a way of making the styles work without breaking this structure?
I am having an issue with rendering my Ant-Design CSS on the first-render using React.js. I have a very basic page, that is just rendering a button.
import React from 'react';
import { Button } from 'antd';
const LoginPage = () => {
return (
<div>
<Button type="primary">Button</Button>
</div>
)
};
export default LoginPage;
I am trying to import the Ant-Design modules through the config-overrides.js file, as per the documentation:
const { override, fixBabelImports } = require('customize-cra');
module.exports = override(
fixBabelImports('import', {
libraryName: 'antd',
libraryDirectory: 'es',
style: 'css',
}),
);
Here is my index.js file:
import { Provider } from 'react-redux';
import thunkMiddleware from 'redux-thunk';
import { createStore, applyMiddleware } from 'redux';
import 'normalize.css';
import App from './components/App/App';
import reducers from './reducers';
import { fetchUser } from './actions';
import * as serviceWorker from './serviceWorker';
const store = createStore(reducers, applyMiddleware(thunkMiddleware));
store.dispatch(fetchUser()).then(() => console.log(store.getState()));
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>,
document.getElementById('root')
);
serviceWorker.unregister();
And here is my App.js and App.css for more reference:
import React, { Component } from 'react';
import LoginPage from '../LoginPage/LoginPage';
import DashboardPage from '../DashboardPage/DashboardPage';
import { Spin } from 'antd';
import './App.css';
import { connect } from 'react-redux';
class App extends Component {
constructor(props){
super(props);
this.state = {
loggedIn: false
}
}
componentDidMount(){
this.setState({loggedIn: true });
}
render() {
return <LoginPage/>
}
}
const mapStateToProps = (state) => {
console.log(state);
return {
user: state.currUser
};
};
export default connect(mapStateToProps)(App);
#import '~antd/dist/antd.css';
However, on the first render it will only show a normal button, before fixing itself a second later. Here are two images that show the problem:
And here is the page after the second render:
Just import this file in your jsx file or js file:
If you import it in App.jsx file once then no need to import in other files
import "antd/dist/antd.css";
Add #import '~antd/dist/antd.css';
To the top of either/both of App.css and Index.css.
Hope that helps! 👍.
P.S - If you are using a single component for instance lets say Input, then import only that part.
import 'antd/es/input/style/index.css';
this below import is used my react project with create-react-app cli
import 'antd/dist/antd.css',
use this import to your root component.
Do NOT import the root styles from ant, as they contain some global styles, unfortunately, and will affect yours styling anyway, this was addressed a lot of times to them, but still I found the only solution is to directly import the components styling like this (replace select with your component):
import "antd/lib/select/style/index.css";
In your index.js file, you can import ant style files:
import 'antd/dist/antd.css';
As of this issue, please use the minified version.
import "antd/dist/antd.min.css";
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.