nested component in React - javascript

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

React | How to get length of divs by id/class?

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 :) ..

How to get value from contentEditable in reactjs

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>
)

Child Component is not able to trigger state change

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;

Digging into state in render of Reactjs app components

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.

React.js Namespaced Components show nothing

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

Categories