can you pass a component through props to children
var TaskForm = require('../../../../components/assessment/tasks/TaskForm.react');
render: function() {
return (
<div>
<div className="row">
<div className="col-xs-12 col-lg-12">
<GroupsItemsAccordionWrapper
TaskForm=TaskForm
/>
</div>
</div>
</div>
);
}
Yes, you can pass any value as a prop, including an object returned by React.createClass (aka component class). Assuming you are implementing dependency injection:
var TaskForm = React.createClass({
render: function() {
return (
<div>{this.props.children}</div>
);
}
});
var GroupsItemsAccordionWrapper = React.createClass({
render: function() {
var TaskForm = this.props.TaskForm;
return (
<div>
<TaskForm>Hello, world!</TaskForm>
</div>
);
}
});
ReactDOM.render(
<GroupsItemsAccordionWrapper TaskForm={TaskForm} />,
document.getElementById('container')
);
(Note the curly brackets around TaskForm={TaskForm}).
Demo: https://jsfiddle.net/69z2wepo/37477/
You can do this like that :
var DivWrapper = React.createClass({
render: function() {
return <div>{ this.props.child }</div>;
}
});
var Hello = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
// create you component
var comp = <Hello name="World" />
ReactDOM.render(<DivWrapper child={ comp }/>, document.body);
And use { this.props.child } to render the component
JSFiddle here : https://jsfiddle.net/5c4gg66a/
Related
This works perfectly fine. Now, I would like to incorporate this into a function and just call the function within my expression. It doesn't work.
Working code:
render: function() {
return (
<div>
{this.props.list.map(function(listValue){
return <p>{listValue}</p>;
})}
</div>
)
}
});
ReactDOM.render(<List list={[1,2,3,4,5]} />, document.getElementById('app'));
code with the function (doesn't work):
var List = React.createClass({
addText: function()
{
this.props.list.map(function(listValue){
return <p>{listValue}</p>;
});
},
render: function() {
return (
<div>
{this.addText()}
</div>
)
}
});
ReactDOM.render(<List list={[1,2,3,4,5]} />, document.getElementById('app'));
You've extracted the call to map into another function and maybe assumed the return call inside it was sufficient to return the result of the whole call (it just returns the mapped value for that iteration of map).
You just need to return the result of your map in your addText function:
var List = React.createClass({
addText: function()
{
return ( // <------ADD THIS
this.props.list.map(function(listValue){
return <p>{listValue}</p>;
})
); //<<-----DON'T FORGET TO CLOSE OFF THE NEW BRACKET
},
render: function() {
return (
<div>
{this.addText()}
</div>
)
}
});
Tnx #Thomas altmann, I forgot to make another return prior to my first return
var List = React.createClass({
addText: function()
{
return (this.props.list.map(function(listValue){
return <p>{listValue}</p>;
})
);
},
render: function() {
return (
<div>
{this.addText()}
</div>
)
}
});
ReactDOM.render(<List list={[1,2,3,4,5]} />, document.getElementById('app'));
I have a small problem where I have parent class and child class. I want to modify the state that was initialized in parent class so that I can see updated state in parent class. Here's the code:
var Parent = React.createClass({
getInitialState: function(){
return{
my_value: 0
}
},
_increaseValue: function(){
this.state.my_value++;
},
render: function(){
return(
<div><Child /></div>
)
}
});
var Child = React.createClass({
render: function(){
//at button I want to access _increaseValue function of parent
return (
<div>
<button onClick={_increaseValue}>Increase</button>
</div>
);
}
});
Now when user clicks the button in child class I would like to get the updated my_value in parent class, thus my questions are:
Is it possible?
If yes, how it is done?
Is this good practice or no?
Is it possible?
yes, it is possible
If yes, how it is done?
you can pass parent method to child through props, like so
var Parent = React.createClass({
getInitialState: function(){
return {
my_value: 0
}
},
onChangeValue: function () {
var value = this.state.my_value + 1;
this.setState({
my_value: value
})
},
render: function() {
return <div>
<Child
onChangeValue={ this.onChangeValue }
value={ this.state.my_value }
/>
</div>;
}
});
var Child = React.createClass({
_handleClick: function(){
this.props.onChangeValue();
},
render: function(){
return <div>
<h1> { this.props.value } </h1>
<button onClick={ this._handleClick }>Increase</button>
</div>
}
});
Example
Is this good practice or no?
It is good practice
You need to pass function via props into your child component. And when you need to change you call this function. It is normal practice and react way.
Example:
var Parent = React.createClass({
getInitialState: function(){
return{
my_value: 0
}
},
onChildClick: function() {
this.setState({
my_value: this.state.my_value + 1
})
},
render: function(){
return(
<div>
{this.state.my_value}
<Child onClick={this.onChildClick.bind(this)}/>
</div>
)
}
});
var Child = React.createClass({
_handleClick: function(){
this.props.onClick();
},
render: function(){
return (
<div>
<button onClick={this._handleClick}>Increase</button>
</div>
);
}
});
Example on JSFiddle
I am trying to get to grips with more complex reactjs components. One I example I would like to get working is this packery one
So this is the basic component for the Hellworld example
var Hello = React.createClass({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
ReactDOM.render(
<Hello name="World" />,
document.getElementById('container')
);
//jsfiddle
https://jsfiddle.net/7xzd92s5/4/
taking this forward I would like to get this packery example working - but how do I include the react-packery-mixin - is there a cnd for it. Is this example complete? https://tonicdev.com/npm/nexts-react-packery-mixin
var PackeryMixin = require('react-packery-mixin');
var packeryOptions = {
transitionDuration: 0
};
var Packer = React.createClass({
displayName: 'SomeComponent',
mixins: [PackeryMixin('packeryContainer', packeryOptions)],
render: function () {
var childElements = this.props.elements.map(function(element){
return (
<div className="someclass">
{element.name}
</div>
);
});
return (
<div ref="packeryContainer">
{childElements}
</div>
);
}
});
ReactDOM.render(
<Packer name="Packer" />,
document.getElementById('Packer')
);
as shown in the example below, I'd like MyComponent to dynamically attach an "onClick" event to its children. The onClick event should fire alertView that should be able to call the clicked element method "getValue".
JSFiddle: http://jsfiddle.net/2g638bp8/
How to do this? Thanks
var MyComponent = React.createClass({
alertValue: function () {
// RETRIEVE THE CHILD HERE
alert(child.getValue());
},
render: function () {
var children = React.Children.map(this.props.children, function (c, index) {
return React.addons.cloneWithProps(c, {
ref: 'child-' + index
});
});
return (
<div>
{children}
</div>
);
}
});
var MySubComponent = React.createClass({
getValue: function () {
return this.props.val;
},
render: function () {
return (
<div>{this.props.val}</div>
);
}
});
React.render(
<div>
<MyComponent>
<MySubComponent val="1" />
<MySubComponent val="2" />
<MySubComponent val="3" />
</MyComponent>
</div>,
document.getElementById('container')
);
You can't call methods on child components in React. You can only set properties. (The child is actually a ReactElement which contains information about the class and associated properties. It is not an instance of the component you created).
So, you could think about this a slightly different way and move the onClick to the MySubComponent:
var MyComponent = React.createClass({
onHandleGiveValue: function (value) {
alert(value);
},
render: function () {
const children = React.Children.map(this.props.children, child => React.cloneElement(child, { onGiveValue: this.onHandleGiveValue.bind(this) }));
return (
<div>
{children}
</div>
);
}
});
var MySubComponent = React.createClass({
handleClick: function() {
this.props.onGiveValue(this.props.val);
},
getValue: function () {
return this.props.val;
},
render: function () {
return (
<div onClick={ this.handleClick } >{this.props.val}</div>
);
}
});
React.render(
<div>
<MyComponent>
<MySubComponent val="1" />
<MySubComponent val="2" />
<MySubComponent val="3" />
</MyComponent>
</div>,
document.getElementById('container')
);
By doing that, your code can pass the current value as an event to the parent component. I've created a new event from the MySubComponent class named onGiveValue. That for now just passes the value from this.props.val. But, it could of course be anything.
Pass the parent callback to the subComponent, one dont need a reference for the child component.
React prefers composition design pattern, So your parent component should contains those three subComponent.
JS Fiddle: http://jsfiddle.net/68vt3umg/
var MyComponent = React.createClass({
handleChildClick: function (e, childValue) {
alert(childValue);
},
render: function () {
return (
<div>
<MySubComponent val="1" onSubClicked={this.handleChildClick}/>
<MySubComponent val="2" onSubClicked={this.handleChildClick}/>
</div>
);
}});
var MySubComponent = React.createClass({
getValue: function () {
return this.props.val;
},
handleOnClick: function (e, value) {
this.props.onSubClicked(e, this.props.val);
},
render: function () {
return (
<div onClick={this.handleOnClick}>{this.props.val}</div>
);
}
});
React.render(
<div>
<MyComponent />
</div>,
document.getElementById('container')
);
I'm trying to bind a value to a div with react so that I can maintain state for that element (eg. on-off) It looks like I should be using LinkedStateMixin, but my experiment below proves that react doesn't support arbitrary attributes for block level elements. Both elements have default values but the div e.target.value returns undefined from its onclick handler whereas the input element value has been properly set. Any idea how to bind data to the div? Thanks!
var Component = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {message: 'Hello!'};
},
render: function () {
var valueLink = this.linkState('message');
var handleClick = function(e) {
console.log(e.target.value);
valueLink.requestChange(e.target.value);
};
return (
<div>
<input type="text" onClick={handleClick} defaultValue={valueLink.value} />
<div onClick={handleClick} defaultValue={valueLink.value}>
{this.state.message}
</div>
</div>
);
}
});
React.render(<Component />, document.body);
http://jsfiddle.net/su8r5Lob/
var Component = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {
message: 'Hello!',
active: false
};
},
inputClick : function(e) {
console.log(e.target.value);
},
toggleActive : function(e){
console.log('div state', this.state.active);
var newState = !this.state.active;
this.setState({active: newState});
},
render: function () {
var cx = React.addons.classSet;
var valueLink = this.linkState('message');
var classes = cx({
'base-class': true,
'element-active': this.state.active
});
return (
<div>
<input type="text" onClick={this.inputClick} defaultValue={valueLink.value} />
<div onClick={this.toggleActive} className={classes}>
{this.state.message}
</div>
</div>
);
}
});
React.render(<Component />, document.body);
http://jsfiddle.net/su8r5Lob/1/
The reason your code does not work is because <div> elements do not have a value property. Only elements that receive user input have it. So when handleClick is called, valueLink.requestChange receives undefined as a parameter.
I've updated your Fiddle a little bit, and now it does support two-way binding for the onChange event.
var Component = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {message: 'Hello!'};
},
render: function () {
var valueLink = this.linkState('message');
var handleClick = function(e) {
console.log(e.target.value);
valueLink.requestChange(e.target.value);
};
return (
<div>
<input type="text" onChange={handleClick} value={valueLink.value} />
<input type="text" onChange={handleClick} value={valueLink.value} />
</div>
);
}
});
React.render(<Component />, document.body);
But, if you want to bind it to a div element, I give you this suggestion. I'm not sure if it is exactly what you expect, but here it is:
var Component = React.createClass({
mixins: [React.addons.LinkedStateMixin],
getInitialState: function() {
return {message: 'Hello!'};
},
render: function () {
var valueLink = this.linkState('message');
var handleClick = function(e) {
console.log(e.target.value);
valueLink.requestChange(e.target.value);
};
return (
<div>
<input type="text" onChange={handleClick} value={valueLink.value} />
<div onClick={handleClick.bind(this, {target: {value: 'someDivValue'}})} defaultValue={valueLink.value}>
{this.state.message}
</div>
</div>
);
}
});
React.render(<Component />, document.body);
Note that I gave the div a default value that is going to be set to the valueLink everytime the user clicks it. And I had to change the event on the input to onchange so it can update its value when the user types something.