I have 3 level nested components. Html structure is like below. C and D's render node/element need to access state and custom function from Main, but C and D are inside B element. I am not sure if this is the best way to structure components. In addition, how do you pass down state and custom functions from Main to grandchildren C and D's render node/element?
<div id="Main">
<div class="A"></div>
<div class="B">
<div class="C"></div>
<div class="D"></div>
</div>
</div>
My attempt:
var Main = React.createClass({
render: function(){
return (
<div className="Main">
<A/>
<B />
</div>
);
}
});
// Putting C, D into B, but C,D both need to access state from Main.
var B = React.createClass({
render: function(){
return (
<div className="B">
<C />
<D />
</div>
);
}
});
var C =....;
var D =....;
React.render(<Main />, document.body)
I am not sure there is a direct way to access the state of child components. But you can use ref.
<Field ref="field1"/>
Then you can use
this.refs.field1.state
Your case:
var B = React.createClass({
render: function(){
return (
<div>
<C ref = "c1"/>
<D ref = "d1"/>
</div>
);
}
});
But this is not recommended as per this link
You may pass the state from Main as props of B
var Main = React.createClass({
getInitialState:function(){
return {mainState:"Main state"}
}
render: function(){
return (
<div>
<A/>
<B mainState={this.state.mainState}/>
</div>
);
}
});
// Putting C, D into B, but C,D both need to access state from Main.
var B = React.createClass({
propTypes:{mainState:React.PropTypes.string}
render: function(){
return (
<div>
{this.props.mainState}// The state from main is received as propps in child component
<C mainState={this.props.mainState}/>// Now youcan access mainState a props of C
<D />
</div>
);
}
});
Related
I need to find the length of child element divs
<div className="intentContainer">
<div className="intent">
</div>
<div className="intent">
</div>
</div>
Here is my code. Need to find no of 'intent' elements
You can use callback ref.
ref={(ele) => this.myEle = ele
put callback ref on parent node which length or child count you want.
return (<div style={styles} ref={(ele) => this.myEle = ele}>
<div >Hello World</div>
<h2>Start editing to see some magic happen {'\u2728'}</h2>
</div>);
Use componentDidMount or componentDidUpdate life cycle to get the length.
componentDidMount(){
console.log(this.myEle.children.length); //2
}
Working React#codesandbox demo
You can use ReactDOM.findDOMNode, even-though the documentation encourages using ref.
DEMO
You need to put ref on parent node.
<div ref="intentContainer" className="intentContainer"></div>
Use the following code in our componentDidMount method.
componentDidMount(){
// get this intentContainer using ref (Its your parent)
var intentContainer = this.refs.intentContainer;
// this will return the count of all childrens
var childrenCount = this.refs.intentContainer.children.length;
// get the count by particular class name from parent dom
var countByClass = ReactDOM.findDOMNode(intentContainer).getElementsByClassName('intent').length;
}
And your render method like as follows,
render() {
return (
<div ref="intentContainer" className="intentContainer">
<div className="intent">
</div>
<div className="intent">
</div>
</div>
);
}
For more help please check to here and here.
Hoeps this will help you !!
import React, { Component } from "react";
export default class SampleComponent extends Component {
intentCount(){
console.log(document.querySelectorAll('.intent').length)
}
render() {
return (
<div className="intentContainer">
<div className="intent">
</div>
<div className="intent">
</div>
<div className="intent">
</div>
<button onClick={this.intentCount}>Intent Count</button>
</div>
);
}
}
This should work :) ..
I'm fairly new to ReactJS. I am looking to get the value inside a <div> when contentEditable is set to true.
const listResults = this.state.results['1'].map((result) =>
<div key={result.toString()} contentEditable="true">
{result}
</div>
);
return (
<h1> listResults </h1>
<div> {listResults} </div>
)
I am currently outputting a list into pre-filled text-boxes which allows the user to edit them. I am looking to add in a button which once clicked captures the data inside all of the text-boxes. Can anyone point me in a direction on how to capture the changed data.
It may also be worth noting I am using ReactJS on the client side through a CDN.
To get value of editable div:
class App extends React.Component {
constructor(){
super();
this.state = {
arr: [1,2,3,4,5]
}
this.change = this.change.bind(this);
}
change(e, index){
let tmpArr = this.state.arr;
tmpArr[index] = e.target.textContent;
this.setState({arr: tmpArr})
}
render(){
console.log(this.state);
return (
<tr>
{this.state.arr.map((el, index) => <td key={index} id="test" onBlur={(e) => this.change(e, index)} contentEditable="true">{el}</td>)}
</tr>
);
}
}
https://jsfiddle.net/69z2wepo/84647/
One note, you can't return two elements on the same level:
return (
<h1> listResults </h1>
<div> {listResults} </div>
)
It should be wrapped like this:
return (
<div>
<h1> listResults </h1>
<div> {listResults} </div>
</div>
)
Simple React State Example. The parent component is App which starts out just showing a button, when the button is clicked it should render AllRecipes (this works and I am able to manage state of AllRecipes). Inside AllRecipes is a button which needs to trigger a state change to then further render ingredients (this button does nothing when clicked, it needs to toggle the state of ingredients). I think this is a really good small example of how to manage state but I am missing something..
var App = React.createClass({
getInitialState: function(){
return {showIngredients: false, showRecipes: false};
},
toggleRecipes: function(){
this.setState({showRecipes: !this.state.showRecipes})
},
toggleIngredients: function(){
this.setState({showRecipes: !this.state.showRecipes})
},
render: function() {
var recipes = this.state.showRecipes ? <Recipes/> : null;
return (
<div>
<h1> Recipe App </h1>
<button onClick={this.toggleRecipes}> Show Recipes </button>
{recipes}
</div>
);
}
});
var Recipes = React.createClass({
render: function() {
var ingredients = this.props.showIngredients ? <Ingredients/> : null;
return (
<div>
<h1> list of recipes </h1>
<ul>
<li> Chicken Soup </li>
<li> Chicken Wings </li>
<button onClick={this.props.toggleIngredients}> Show Recipes </button>
{ingredients}
</ul>
</div>
);
}
});
var Ingredients = React.createClass({
render: function() {
return (
<div>
<h1> List of Ingredients </h1>
<ul>
<li> Salt </li>
<li> Pepper </li>
</ul>
</div>
);
}
});
React.render(<App/>, document.body);
It looks like you aren't passing toggleIngredients to Recipes. Try changing
var recipes = this.state.showRecipes ? <Recipes/> : null;
to
var recipes = this.state.showRecipes ? <Recipes toggleIngredients={this.toggleIngredients} /> : null;
I cannot reference elements of objects and arrays in a state passed to a subcomponent.
I have not been able to clearly identify the difference between the cases when I cannot reference them in some sub components.
What is the thing I miss?
Sample props of the components is given under the components. Commented.
In that I cannot reference for example, current.main.temp or current.weather[0]. it gives an undefined error:
var Current = React.createClass({
render: function () {
var current = this.props.current;
var dateArray = new Date(current.dt * 1000).toDateString().split(" ");
console.log("datearray: ", dateArray[0]);
var main = current.main;
console.log(main);
return (
<div style={{float: "left", clear:"left"}}>
<div style={{float: "left"}}>
<div>{dateArray[0]}</div>
<div>{dateArray[1]} {dateArray[2]}</div>
<div>{dateArray[3]}</div>
</div>
<div style={{float: "left"}}>
<div>current: {JSON.stringify(current)}</div>
</div>
<div style={{float: "left", clear: "right"}}>
<div>{JSON.stringify(current.weather)}</div>
</div>
</div>
);
},
});
// {"coord":{"lon":32.85,"lat":39.92},"weather":[{"id":801,"main":"Clouds","description":"few clouds","icon":"02d"}],"base":"cmc stations","main":{"temp":28,"pressure":1018,"humidity":34,"temp_min":28,"temp_max":28},"wind":{"speed":2.1},"clouds":{"all":20},"dt":1442483400,"sys":{"type":1,"id":6022,"message":0.0026,"country":"TR","sunrise":1442460682,"sunset":1442505249},"id":323786,"name":"Ankara","cod":200}
however, in that I can reference for example, current.main.temp or current.weather[0]:
var Hour = React.createClass({
render: function () {
var hour = this.props.hour; // is an object.
return (
<div style={{float: "left"}}>
<div>{hour.weather[0].main}</div>
<div>{hour.weather[0].description}</div>
<div><img src={"http://openweathermap.org/img/w/"+hour.weather[0].icon+".png"} /></div>
<div>{hour.main.temp}</div>
<div>{hour.main.temp_min}</div>
<div>{hour.main.temp_max}</div>
<div>{hour.main.humidity}</div>
<div>{new Date(hour.dt * 1000).getHours()} o,clock</div>
</div>
);
}
});
// {"dt":1442437200,"main":{"temp":16.39,"temp_min":14.78,"temp_max":16.39,"pressure":914.76,"sea_level":1026.82,"grnd_level":914.76,"humidity":67,"temp_kf":1.62},"weather":[{"id":800,"main":"Clear","description":"sky is clear","icon":"01n"}],"clouds":{"all":0},"wind":{"speed":1.41,"deg":308.503},"sys":{"pod":"n"},"dt_txt":"2015-09-16 21:00:00"}
It's because of your data structure.
You don't have any property called data in your weather data making current.data.dt and current.data.main be undefined.
In the official document React.js, there is a new feature:Namespaced Components from version 0.11.
REF:http://facebook.github.io/react/docs/jsx-in-depth.html
var Form = MyFormComponent;
var App = (
<Form>
<Form.Row>
<Form.Label />
<Form.Input />
</Form.Row>
</Form>
);
var MyFormComponent = React.createClass({ ... });
MyFormComponent.Row = React.createClass({ ... });
MyFormComponent.Label = React.createClass({ ... });
MyFormComponent.Input = React.createClass({ ... });
So, I refer it and write following code to create a component
var MysearchPage=React.createClass({
render:function(){
return (
<div>
</div>
);
}
});
MysearchPage.Title=React.createClass({
render:function(){
return (
<h1>MysearchPage!</h1>
);
}
});
MysearchPage.Search= React.createClass({
render:function(){
return (
<div>
{this.props.searchType}:<input type="text"/>
<button>Search</button>
</div>
);
}
});
var SearchPage=MysearchPage;
var App=(
<SearchPage>
<SearchPage.Title />
<SearchPage.Search searchType="Content"/>
</SearchPage>
);
React.render(
App,
document.getElementById('nuno')
);
Finally,there is no error message,but it show nothing and I cannot see result.I want to know why it show nothing and where is error.
I guess "SearchPage.Title" node do not append to "SearchPage".
Because I change code:
var App=(
<div>
<SearchPage.Title />
<SearchPage.Search searchType="Content"/>
</div>
);
Perhaps, it can get result.
So,I have another problem.
var MysearchPage=React.createClass({
render:function(){
return (
<div>
</div>
);
}
});
What is the difference between the above code and pure HTML tag ? Thank you!
The render function of Mysearchpage just returns an empty div, so you'll have to explicitly render all its component children:
render:function(){
return (
<div>
{this.props.children}
</div>
);
See https://facebook.github.io/react/docs/multiple-components.html