React inline styles, applying styles from state - javascript

Using npm-inline-css module, I'm trying to change certain page elements colors, when storing the styles in a state. I set the state here:
setHeaderStyle: function(data){
var headerStyles = this.state.defaultStyles;
if(data) {
headerStyles.backgroundColor = data.first_colour;
headerStyles.color = data.theme;
}
this.setState({
branding: data,
headerStyles: headerStyles
});
},
Then I'm trying to apply the styles to the component:
render: function (){
return (
<div className="our-schools-app">
<InlineCss stylesheet="
& .button {
color: {{this.state.color}};
}
" />
<RouteHandler />
</div>
);
}
But they output like below. How can I set the inline styles? Or a better way I can do this?
<style scoped="" data-reactid=".0.0.1">#InlineCss-0 .button { color: {{this.state.color
}
}
;
}
</style>

From React Docs:
In React, inline styles are not specified as a string. Instead they are specified with an object whose key is the camelCased version of the style name, and whose value is the style's value, usually a string.
It looks like you're most likely trying to set styles for a button that exists in components that are rendered in RouteHandler.
If that's the case, it would make the most sense for you to create a wrapper that wraps the other components and accepts the styles you're trying to set.
For example:
var PageWrapper = React.createClass({
setHeaderStyle: function(data){
var headerStyles = this.state.defaultStyles;
if(data) {
headerStyles.backgroundColor = data.first_colour;
headerStyles.color = data.theme;
}
this.setState({
branding: data,
headerStyles: headerStyles
});
},
render: function () {
var buttonStyle = {
color: this.state.color
}
return (
<RouteHandler buttonStyle={buttonStyle} />
);
}
});
var Index = React.createClass({
render: function () {
return (
<div>
<RouteHandler />
</div>
);
}
});
var Signup = React.createClass({
render: function() {
return (
<div>
<p> Click below to signup now! </p>
<button style={this.props.buttonStyle}>Click Me!</button>
</div>
);
}
});
var Contact = React.createClass({
render: function() {
return (
<div>
<p> Click the button below to contact us </p>
<button style={this.props.buttonStyle}>Email Us!</button>
</div>
);
}
});
var routes = (
<Route path="/" handler={Index}>
<Route path="page" handler={PageWrapper}>
<Route path="signup" handler={Signup} />
<Route path="contact" handler={Contact} />
</Route>
</Route>
);
ReactRouter.run(routes, function (Handler) {
React.render(<Handler/>, document.body);
});
Edit: Per your request, as an example to show how nested routes would work, I added a Signup and Contact component. If you look at the routes variable you can see how I nested these components under PageWrapper.
Now the nested routes /#/page/signup and /#/page/contact will both get access to the props that are added to the <RouteHandler /> of PageWrapper. Hope this helps!!!!!

Related

React: Adding props only to React component and not html tag (React.Children.map recursively)

I have a Form's React component that manage several Field's component and attach to them some props.
Until now, I created only simple form, like this
<Form>
<FieldText/>
<FieldDropdown />
</Form>
but now, I need a form with more complex structure, like this
<Form>
<div>
<a data-tab="first">First Tab</a>
<a data-tab="second">Second Tab</a>
</div>
<div data-tab="first">
<FieldText />
</div>
<div data-tab="second">
<FieldText />
</div>
</Form>
With simple form I added props to Fieldin this way
var Form = React.createClass({
render: function(){
<form onSubmit={this.submit} acceptCharset="UTF-8" ref={cForm.id}>
{
React.Children.map(this.props.children, child => {
// if type is funtion the is a react component
if( typeof child.type === "function"){
return React.cloneElement(child, {
attachToForm: this.attachToForm,
disabled: this.props.disabled
});
} else {
return child;
}
})
}
</form>
}
});
How can I modify Form to add some props only to Field's component and not
html tag?
Each child component should have a type field, for normal html elements, this would be a string such as "span", "div", etc.
You can simply switch (or your conditional of choice) against that field.
Simple abstracted version would be like:
const Foo = (props) => (
<div style={props.style}>FOO</div>
);
class App extends React.Component {
render () {
return (
<div>
{ React.Children.map(this.props.children, child => {
if(typeof child.type === 'string') {
switch(child.type) {
case 'span':
return React.cloneElement(child, { style: { background: 'pink' }});
case 'div':
return React.cloneElement(child, { style: { background: 'red' }});
}
} else {
switch(child.type.name) {
case 'Foo':
return React.cloneElement(child, { style: { background: 'blue' }});
}
}
return child;
})}
</div>
);
}
}
ReactDOM.render(
<App>
<span>span</span>
<p>p</p>
<Foo />
<div>div</div>
</App>,
document.getElementById('root')
);
With codepen:
http://codepen.io/cjke/pen/qRQvmY?editors=0010
EDIT
Based on the comments, the question is more about recursively walking the DOM tree - in which, its simple a duplicate of this question: React.Children.map recursively?

map images concatenating strings

I am using the map function to iterate over an array with images. I am then trying to display these images on the page.
You will see that the images are being concatenated into one stain. Does anyone know how to do this so i can show each individual image?
I have set up a jsfiddle here
Please see React code below:
var App = React.createClass({
render: function(){
var images = [
{
id:"1",
images:['https://i.scdn.co/image/dc284fcd7e581aa2b7ca56f28c7c74f0ca0ad393', 'https://i.scdn.co/image/97ffc63dd5abfe7203d8f5e90d1a74427ac756e7']
},
{
id:"2",
images:['https://i.scdn.co/image/97ffc63dd5abfe7203d8f5e90d1a74427ac756e7', 'https://i.scdn.co/image/97ffc63dd5abfe7203d8f5e90d1a74427ac756e7']
}
];
return(<List images={images} />)
}
});
var List = React.createClass({
render: function() {
var images = this.props.images.map(function(image){
return(image.images[0]); // updated here
})
return(
<div>
<img src={images}></img>
<p>{images}</p>
</div>
)
}
});
ReactDOM.render(
<App name="World" />,
document.getElementById('container')
);
Does the following work? https://jsfiddle.net/petebere/19fmn5qs/
The change was to add the <img /> tag with the src attribute set to the url:
var images = this.props.images.map(function(image, index){
return <img key={index} src={(image.images[0])} />;
});
Also, you now don't need the <img /> tag in your final return statement. Please see my updated fiddle. I've also added the key attribute as required in the React docs: https://facebook.github.io/react/docs/multiple-components.html#dynamic-children
Full code:
var App = React.createClass({
render: function() {
var images = [
{
id:"1",
images:['https://i.scdn.co/image/dc284fcd7e581aa2b7ca56f28c7c74f0ca0ad393', 'https://i.scdn.co/image/97ffc63dd5abfe7203d8f5e90d1a74427ac756e7']
},
{
id:"2",
images:['https://i.scdn.co/image/97ffc63dd5abfe7203d8f5e90d1a74427ac756e7', 'https://i.scdn.co/image/97ffc63dd5abfe7203d8f5e90d1a74427ac756e7']
}
];
return(<List images={images} />);
}
});
var List = React.createClass({
render: function() {
var images = this.props.images.map(function(image, index){
return <img key={index} src={(image.images[0])} />;
});
return(
<div>
<p>Your images</p>
{images}
</div>
);
}
});
ReactDOM.render(
<App name="World" />,
document.getElementById('container')
);

react state bind from child to parent element

I am new to reactJS
I have an JSON array which consists of task. I have rendered the the array to 2 ul list. One has completed tasks and the other has uncompleted tasks. If i click on the task the status is changing but it is not updated in other element. However if I enter some text in the input state is set to other elements. Why the state is not set immediately when I click on task?
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/0.13.3/JSXTransformer.js"></script>
<body>
<div id="todo">
</div>
<script type="text/jsx">
var TodoList = React.createClass({
clickHandle: function(index) {
this.props.items[index].completed=!this.props.items[index].completed;
console.log(this.props);
this.setState({items: this.props.items});
},
render: function() {
var createItem = function(itemText, index) {
if(itemText.completed===this.props.completed)
return <li key={index} onClick={this.clickHandle.bind(this,index)}>{itemText.text}</li>;
};
return <ul>{this.props.items.map(createItem, this)}</ul>;
}
});
var TodoApp = React.createClass({
getInitialState: function() {
return {items: [{"text":"1true","completed":true},{"text":"2true","completed":true},{"text":"1false","completed":false}], text: ''};
},
onChange: function(e) {
this.setState({text: e.target.value});
},
handleSubmit: function(e) {
e.preventDefault();
if(this.state.text!=''){
this.state.items.push({"text":this.state.text,"completed":false});
var nextText = '';
this.setState({items:this.state.items,text: nextText});
}
else{
alert("Enter some text!");
}
},
render: function() {
return (
<div>
<h3>TODO</h3>
<TodoList items={this.state.items} completed={false}/>
<TodoList items={this.state.items} completed={true}/>
<form onSubmit={this.handleSubmit}>
<input onChange={this.onChange} value={this.state.text} />
<button>{'Add #' + (this.state.items.length + 1)}</button>
</form>
</div>
);
}
});
React.render(<TodoApp />, document.getElementById('todo'));
</script>
JSFiddle
This is happening because the parent component, TodoApp which renders the two lists does not know that something has changed in one of the them. For this the child component should notify the parent component about it.
Add a onStatusUpdate attribute to TodoList like this
<TodoList items={this.state.items} completed={false} onStatusUpdate={this.update}/>
This is how the update method can be defined
update: function(items){
this.setState({items: items});
}
In the click handler of child component do something like this
clickHandle: function(index {
this.props.items[index].completed=!this.props.items[index].completed;
this.props.onStatusUpdate(this.props.items); // <-- this triggers the onStatusUpdate attribute defined in TodoList component
},
Here is an updated demo https://jsfiddle.net/dhirajbodicherla/aqqcg1sa/2/`

How to transfer props in react v0.13?

I'm trying to learn react for my first javascript project and as a start creating a very simple code that adds two numbers entered in a text box. The result is re-rendered as a number is typed. This worked for me on react v0.11.
var App = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {
payment: 0,
payment2: 0
};
},
render: function() {
var total = parseInt(this.state.payment, 10) +
parseInt(this.state.payment2, 10);
return (
<div>
<Payment {...this.props} valueLink={this.linkState('payment')}/><span>+</span>
<Payment {...this.props} valueLink={this.linkState('payment2')}/><span>=</span>
{ total }
</div>
);
}
});
var Payment = React.createClass({
render: function() {
return this.transferPropsTo(
<input type="text" />
);
}
});
React.render(
<App />,
document.getElementById('app')
);
However, it seems like the transferPropsTo() function was removed in v0.13. How do I do the equivalent in the latest version.
You can pass {...this.props} in the input tag:
var Payment = React.createClass({
render: function() {
return (
<input type="text" {...this.props} />
);
}
});
This uses the JSX spread attributes feature.

Render new element onClick in react.js

I'm new to react and am trying to render a new element onClick:
var LoginButton = React.createClass({
..............
..............
clickHandle : function() {
this.rememberMe = {
active: localforage.getItem('rememberMe', function (err, key) {
return key;
})
};
if (this.rememberMe.active == true || this.rememberMe.active == 'checked')
{
document.getElementById('loginForm').submit();
}
else {
React.render(<wantToRemember />, document.getElementById('loginbuttonhere'));
}
return this.rememberMe.active;
},
This is the element that should appear:
var wantToRemember = React.createClass({
getInitialState : function () {
return {
position: 'absolute',
display: 'block',
top: '20px',
width: '100px',
height: '100px'
}
},
render : function () {
return (
<div className="rememberPopup" style={this.state}>
<div className="row">
<div className="staylogin">
<div className="col-md-4">
<label for="checkbox">Angemeldet bleiben</label>
</div>
<div className="col-md-1">
<input type="checkbox" id="checkbox" name="remember" />
</div>
</div>
</div>
</div>
);
}
});
but it doesn't appear, instead react renders this html:
<wanttoremember data-reactid=".1"></wanttoremember>
I'm pretty sure I'm doing some pretty basic stuff wrong, but can't figure out what. Isn't it possible to call different elements like this?
Your react.js component name begins with a lower-case letter, it should start with an upper-case leter: var WantToRemember = React.createClass(...) and React.render(<WantToRemember />,....
The JSX compiler requires for component names to begin with an upper-case letter (see jsx docs on this):
To render a React Component, just create a local variable that starts with an upper-case letter:
var MyComponent = React.createClass({/*...*/});
var myElement = <MyComponent someProperty={true} />;
React.render(myElement, document.getElementById('example'));
You should pass a React element to React.render instead of the tag itself, something like this:
React.render(
React.createElement(wantToRemember)
);

Categories

Resources