Is there a way to add external (eg. bootstrap) classes along with react-emotion styling?
import React, { Component } from 'react';
import { css } from 'react-emotion';
const MyStyle = css`
STYLE
`
export default class MyComponent extends Component {
render() {
return (<button className={css`${MyStyle}` /* add in some way `btn btn-default` */ }>Text</button>);
}
}
Thanks!
Yes you can. Below is the link where i had made a small example, the font colour is coming from react-emotion and background colour is coming from bootstrap.
import React, { Component } from 'react';
import { render } from 'react-dom';
import 'bootstrap/dist/css/bootstrap.min.css';
import styled, { css } from 'react-emotion'
const myStyle = css`
color: rebeccapurple;
`;
class App extends Component {
constructor() {
super();
this.state = {
name: 'React'
};
}
render() {
return (
<div className={myStyle + ' bg-primary'}>Hello World</div>
);
}
}
render(<App />, document.getElementById('root'));
Related
What I would like is to create a code that 'shoots' out some image from the center of the screen to some random trajectory.
Here is the descriptional code I would like to achieve:
class Name extends React.Component{
render(){
return (
<img animation moving from centre to some random trajectory>
after few seconds...
<another img animation (the same one) moving from centre to some other random trajectory>
<do it many more times, until event occurs that will stop it>
);
}
}
I have made components that create interface, and that render an image animation of movement from centre to some random trajectory, but only once. I don't know how to make it repeatedly.
index.js
import React from 'react';
import ReactDOM from 'react-dom';
import "./bootstrap/css/bootstrap.css";
import {CreateEnvironment} from './components/createEnvironment';
import {SheepsStart} from './components/sheepsStart';
class MainComponent extends React.Component {
render(){
return (
<React.Fragment>
<CreateEnvironment />
<SheepsStart />
</React.Fragment>
);
}
}
ReactDOM.render(<MainComponent/>, document.getElementById('root'));
Component CreateEnvironment is irrelevant, it creates 3 drawing divs.
Component SheepsStart:
import React from 'react';
import {CreateSheeps} from './createSheeps';
import sheep from '../images/sheep.png';
export class SheepsStart extends React.Component {
render(){
return (
<React.Fragment>
<CreateSheeps src = {sheep} alt = "Sheep"/>
</React.Fragment>
);
}
}
Styled component, which I needed so I could insert random #keyframes:
import styled from 'styled-components';
import { sheepWantsToEscape } from './KeyFrames';
export const CreateSheeps = styled.img`
width:2.5%;
z-index: 1;
position:absolute;
left:48.75%;
bottom:48.75%;
animation: ${sheepWantsToEscape} 4s;
animation-iteration-count:1;
animation-timing-function:linear;
`
export default CreateSheeps;
Component with #keyframes with random trajectory coordinates.Function createTrajectory calculates coordinates, and returns an array of two.
import styled, { keyframes } from 'styled-components';
import {createTrajectory} from './helperFunction';
let coordinates = createTrajectory();
export const sheepWantsToEscape = keyframes`
0% {
left:48.75%;
bottom:48.75%;
}
100% {
left:${coordinates[0]}%;
bottom:${coordinates[1]}%;
}
This is only an example, if you point out what you've tried out I'll can be more specific:
const base = 100;
class Hello extends React.Component {
state = {
myStyle : {
marginTop: base,
marginLeft: -base,
}
}
plusMinus = () => Math.random() < 0.5 ? -1 : 1;
randomize = () => {
this.setState({
myStyle: {
marginTop: Math.random()*base*this.plusMinus(),
marginBottom: Math.random()*base*this.plusMinus(),
},
});
}
render() {
return <div><img
style={{...this.state.myStyle}} src="https://upload.wikimedia.org/wikipedia/commons/thumb/a/a7/React-icon.svg/200px-React-icon.svg.png" />
<button onClick={this.randomize}>move</button>
</div>;
}
}
ReactDOM.render(
<Hello name="World" />,
document.getElementById('container')
);
https://jsfiddle.net/vya19fz2/
Within my React+StyledComponent app, I have a theme file like so:
theme.js:
const colors = {
blacks: [
'#14161B',
'#2E2E34',
'#3E3E43',
],
};
const theme = {
colors,
};
export default theme;
Currently, I can easily use these colors to style my components like so:
const MyStyledContainer = styled.div`
background-color: ${(props) => props.theme.colors.blacks[1]};
`;
The problem is, how do I pass blacks[1] to a Component as the prop of the color to use like so:
<Text color="black[1]">Hello</Text>
Where Text.js is:
const StyledSpan = styled.span`
color: ${(props) => props.theme.colors[props.color]};
`;
const Text = ({
color,
}) => {
return (
<StyledSpan
color={color}
>
{text}
</StyledSpan>
);
};
Text.propTypes = {
color: PropTypes.string,
};
export default Text;
Currently the above is silently failing and rending the following in the DOM:
<span class="sc-brqgn" color="blacks[1]">Hello</span>
Any ideas on how I can get this to work? Thank you
EDIT: Updated to use styled-components withTheme HOC
New answer
You could wrap the component rendering <Text> in the higher order component (HOC) withTheme provided by styled-components. This enables you to use the theme given to the <ThemeProvider> directly in the React component.
Example (based on the styled-components docs):
import React from 'react'
import { withTheme } from 'styled-components'
import Text from './Text.js'
class MyComponent extends React.Component {
render() {
<Text color={this.props.theme.colors.blacks[1]} />;
}
}
export default withTheme(MyComponent)
Then you could do
const MyStyledContainer = styled.div`
background-color: ${(props) => props.color};
`;
Old answer
You could import the theme where you render and pass <Text color={theme.blacks[1]} />.
import theme from './theme.js'
...
<Text color={theme.colors.blacks[1]} />
Then you could do
const MyStyledContainer = styled.div`
background-color: ${(props) => props.color};
`;
You can use defaultProps
import PropTypes from 'prop-types'
MyStyledContainer.defaultProps = { theme }
App.js
App gets theme and passes color to Text
import React, { Component } from 'react'
import styled from 'styled-components'
const Text = styled.div`
color: ${props => props.color || 'inherit'}
`
class App extends Component {
render() {
const { theme } = this.props
return (
<Text color={theme.colors.black[1]} />
)
}
}
export default App
Root.js
Root component passes theme to entire application.
import React, { Component } from 'react'
import { ThemeProvider } from 'styled-components'
import theme from './theme'
import App from './App'
class Root extends Component {
render() {
return (
<ThemeProvider theme={theme}>
<App />
</ThemeProvider>
)
}
}
export default Root
If you're using functional components in React and v4.x and higher styled-components, you need to leverage useContext and styled-components' ThemeContext. Together, these allow you to use your theme settings inside of components that aren't styled-components.
import { useContext } from 'react'
import { ThemeContext } from 'styled-components'
export default function MyComponent() {
// place ThemeContext into a context that is scoped to just this component
const themeProps = useContext(ThemeContext)
return(
<>
{/* Example here is a wrapper component that needs sizing params */}
{/* We access the context and all of our theme props are attached to it */}
<Wrapper maxWidth={ themeProps.maxWidth }>
</Wrapper>
</>
)
}
Further reading in the styled-components docs: https://styled-components.com/docs/advanced#via-usecontext-react-hook
I know that the following snippet gets optimized if styles are created by Stylesheet.create() and Child extends PureComponent.
import React, { Component } from 'react'
import { View } from 'react-native'
import Child from './Child'
import styles from './stylesheets'
export default class Parent extends Component {
render() {
return (
<View>
<Child style={styles.x} />
</View>
)
}
}
Does it also works with multiple styles? I'm afraid that [] literals prevent optimization.
import React, { Component } from 'react'
import { View } from 'react-native'
import Child from './Child'
import styles from './stylesheets'
export default class Parent extends Component {
render() {
return (
<View>
<Child style={[styles.x, styles.y]} />
</View>
)
}
}
Or do I need to define combined style statically?
import React, { Component } from 'react'
import { View } from 'react-native'
import Child from './Child'
import styles from './stylesheets'
const childStyles = [styles.x, styles.y]
export default class Parent extends Component {
render() {
return (
<View>
<Child style={childStyles} />
</View>
)
}
}
I confirmed that array literal spoils PureComponent optimization.
I'm trying to pass props to my children components which are under the controller. I'm using redux and react-router for navigation. The problem is that everything is fine in the controller, it gets its initial props, but when I'm passing them to a child I have an undefined either the constructor or in render function. Here is my code:
import React, { Component } from 'react'
import { connect } from 'react-redux'
import moment from 'moment'
import LawsuitSchedule from '../components/LawsuitSchedule'
import LawsuitCalendar from '../components/LawsuitCalendar'
class LawsuitScheduleContainer extends Component {
constructor (props) {
super(props)
}
render () {
let {schedule} = this.props
console.log(schedule)
return (
<LawsuitCalendar initialDate={schedule.initialDate}
selectedDate={schedule.selectedDate}
scheduledDates={schedule.scheduledDates}/>,
<LawsuitSchedule/>
)
}
}
const mapStateToProps = state => ({
schedule: state.schedule,
})
export default connect(mapStateToProps)(LawsuitScheduleContainer)
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import momentPropTypes from 'react-moment-proptypes'
import moment from 'moment'
import DatePicker from 'react-datepicker'
import 'react-datepicker/dist/react-datepicker.css'
import '../styles/lawsuitCalendar.css'
export default class LawsuitCalendar extends Component {
constructor (props) {
super(props)
console.log(props)
}
propTypes = {
selectedDate: momentPropTypes.momentString,
scheduledDates: PropTypes.array.isRequired,
}
handleChange = (date) => {
this.setState({
selectedDate: date,
})
}
render () {
let {selectedDate, scheduledDates} = this.props
let highlightWithRanges = [
{
'scheduled-date': scheduledDates,
},
]
return (
<DatePicker
inline
selected={selectedDate}
onChange={this.handleChange}
highlightDates={highlightWithRanges}
/>
)
}
}
The problem was in another component, which renders LawsuitCalendar too. I have no clue why it was displayed only once, but I have solved my problem with props -- I just didn't pass them. I've added it, maybe someone can answer why has that happened?
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { Grid, Row, Col } from 'react-bootstrap'
import { Link } from 'react-router-dom'
import ReactTable from 'react-table'
import matchSorter from 'match-sorter'
import LawsuitCalendar from '../components/LawsuitCalendar'
import '../styles/lawsuitGrid.css'
import data from '../utils/data.json'
export default class LawsuitSchedule extends Component {
render () {
return (
<Grid>
<Row className="show-grid">
<Col md={4}><LawsuitCalendar/></Col>
<Col md={8}>
<ReactTable data={data}
...
/>
</Col>
</Row>
</Grid>
)
}
}
I am trying to apply a custom theme to my React component after reading this tutorial
http://www.material-ui.com/#/customization/themes
I wrote my theme in a separate javascript file like this
import Colors from 'material-ui/lib/styles/colors';
import ColorManipulator from 'material-ui/lib/utils/color-manipulator';
import Spacing from 'material-ui/lib/styles/spacing';
import zIndex from 'material-ui/lib/styles/zIndex';
export default {
spacing: Spacing,
zIndex: zIndex,
fontFamily: 'Roboto, sans-serif',
palette: {
primary1Color: Colors.cyan500,
primary2Color: Colors.cyan700,
primary3Color: Colors.lightBlack,
accent1Color: Colors.pinkA200,
accent2Color: Colors.grey100,
accent3Color: Colors.grey500,
textColor: Colors.deepPurpleA700,
alternateTextColor: Colors.white,
canvasColor: Colors.white,
borderColor: Colors.grey300,
disabledColor: ColorManipulator.fade(Colors.darkBlack, 0.3),
pickerHeaderColor: Colors.cyan500,
}
};
I apply this theme to my component in the follow way
import React from 'react';
import mui from 'material-ui';
import injectTapEventPlugin from 'react-tap-event-plugin';
import ThemeManager from 'material-ui/lib/styles/theme-manager';
import Colors from 'material-ui/lib/styles/colors';
import MyTheme from './theme.js';
injectTapEventPlugin();
class App extends React.Component {
constructor(props) {
super(props);
this.state = {
messages : [{id: 1, text: 'Hi'}, {id: 2, text: 'Hello'}]
};
}
getChildContext() {
return {
muiTheme: ThemeManager.getMuiTheme(MyTheme)
};
}
componentWillMount() {
let newMuiTheme = this.state.muiTheme;
this.setState({
muiTheme: newMuiTheme,
});
}
render() {
var messageNodes = this.state.messages.map((message) => {
return (<div key={message.id}>{message.text}</div>);
});
return (<div>{messageNodes}</div>);
}
}
App.childContextTypes = {
muiTheme: React.PropTypes.object
};
export default App;
According to my theme when my control renders it should have a "deepPurpleA700" color .... but my control text is always black. So my theme is not applied.
My full code is available at https://github.com/abhitechdojo/MovieLensReact
You should first import your color from 'material-ui/styles/colors'
and then use them in palette object like this :
import React, { Component } from 'react';
import {render} from 'react-dom';
import {indigo500, indigo700, redA200} from 'material-ui/styles/colors';
import getMuiTheme from 'material-ui/styles/getMuiTheme';
import MuiThemeProvider from 'material-ui/styles/MuiThemeProvider';
import injectTapEventPlugin from 'react-tap-event-plugin';
injectTapEventPlugin();
import Main from './Main';
const muiTheme = getMuiTheme({
palette: {
primary1Color: indigo500,
primary2Color: indigo700,
accent1Color: redA200,
pickerHeaderColor: indigo500,
},
});
class App extends Component {
render() {
return (
<div>
<MuiThemeProvider muiTheme={muiTheme}>
<Main />
</MuiThemeProvider>
</div>
);
}
}
render(<App/>, document.getElementById('app')); //you should be having a div with an id of app in your index.html file
and the Main.js file is
import React, { Component } from 'react';
import FloatingActionButton from 'material-ui/FloatingActionButton';
export default class Main extends Component {
render() {
return (
<div>
<AppBar title="Title"/>
<FloatingActionButton secondary={true} />
</div>
);
}
}
For me it worked with:
import React, {Component} from 'react';
import {createMuiTheme} from '#material-ui/core/styles';
import MuiThemeProvider from '#material-ui/core/styles/MuiThemeProvider';
const theme = createMuiTheme({
palette: {
primary: {
main: '#0b5994',
},
secondary: {
main: '#1d83c6',
},
},
});
class App extends Component {
render() {
return (
<div className="App">
<MuiThemeProvider theme={theme}>
/* content here! */
</MuiThemeProvider>
</div>
);
}
}
export default App;
I am pretty sure you need to have
static childContextTypes = {
muiTheme: React.PropTypes.object,
};
before your
getChildContext()
method. Once that is done you should be able to remove any theme related stuff from
componentWillMount()
Now, this won't work for base text. But I can confirm that the theme is being applied. I tested it by adding an appBar component and changing the color in your theme.js file. I also added a List with ListItems and that text style is what you are looking for.
Here is a link to the gist of your modified App.jsx file.
Also, as a side note in you server.js you have a small typo on line 5 you should have
new webpackDevServer(webpack(config), {
not
new WebpackDevServer(webpack(config), {