I'm doing a react app and id I'd like to know how to think multipages websites. Actually i'im I'm doing a course searcher,i searcher; I use routie to render the different components that renders render the page. The problem is that they arent aren't related by hierarchy, so the ajax data isn't accessible to the component that renders the result.I've I've tried vainly to use a js var data but doesnt var data but that doesn't work too either.Ive read https://facebook.github.io/react/tips/communicate-between-components.html
but i don't see what to do with own event system. If someone could illustrate the last paragraph of this doc it is great for all the people that are in this case.
var data = {};
var CourseSearcher = React.createClass({
getInitialState: function(){
return {
return { places: '',
branch: 0,
dayOfMonth: '',
timeStart: '',
timeEnd: '',
data: []};
},;
},
handlePlacesChange: function(e){
this.setState({places: e.target.value});
},
handleBranchChange: function(e){
this.setState({branch: e.target.value});
},
handleDayOfMonthChange: function(e){
this.setState({dayOfMonth: e.target.value});
},
handleTimeStartChange: function(e){
this.setState({timeStart: e.target.value});
},
handleTimeEndChange: function(e){
this.setState({timeEnd: e.target.value});
},
handleSubmit: function(e){
// stop the default browser action
e.preventDefault();
// Do an ajax post
$.ajax({
url:'php/results.php',
dataType: 'json',
type: 'GET',
data: {
data: {places: this.state.places,
branch:this.state.branch,
dayOfMonth:this.state.dayOfMonth,
timeStart:this.state.timeStart,
timeEnd:this.state.timeEnd},
},
success: function(data){
this.setState({data: data});
data = this.state.data;
routie('results');
}.bind(this),
error: function (xhr,status,err){
console.error('php/results.php',status,err.toString());
}.bind(this)
});
},
render: function(){
return(
<div>
<form method="get" onSubmit={this.handleSubmit}>
<label>Où?</label>
<input
type="text"
placeholder="Lieux"
value={this.state.places}
onChange={this.handlePlacesChange}
/>
<label>Quoi?</label>
<select value={this.state.branch} onChange={this.handleBranchChange}>
<option>Matière</option>
<option>Français</option>
<option>Anglais</option>
</select>
<label>Quand ?</label>
<input
type="date"
value={this.state.dayOfMonth}
onChange={this.handleDayOfMonthChange}
/>
<input
type="time"
value={this.state.timeStart}
onChange={this.handleTimeStartChange}
/> -
<input
type="time"
value={this.state.timeEnd}
onChange={this.handleTimeEndChange}/>
<button type="submit">Go!</button>
</form>
</div>
);
}
});
console.log(data);
var ResultList = React.createClass({
render: function() {
console.log(data);
return(
<h1>Hello</h1>);
}
);
}
});
var ResultBox = React.createClass({
render: function() {
return (
<div>
<h4>{}</h4>
</div>
);
}
});
routie({
'':function() {
React.render(<CourseSearcher />,
document.getElementById('content'));
},
'results': function() {
React.render(
React.render(<ResultList results={data} />,
document.getElementById('content'));
}
});
Done well with react router ;)
I've done it with react router where components are related to some dedicated urls
Related
I'm trying to create a menu where the user should create a character details but I'm having an issue to update the Options states through an input of a child.
var Name = React.createClass({
render: function(){
return(
<input type="text"/>
)
}
});
var Options = React.createClass({
getInitialState: function(){
return{
name: ''
}
},
render: function(){
return (
<div>
Name: <Name onChange={this.updateName} value={this.state.name} />
</div>
)
},
updateName: function(evt){
this.setState({
name: evt.target.value
});
}
});
How can I go about updating the Option states using the input from Name?
you need onChange function on the Name component as well, that sends the value to the parent component
Try this:
var Name = React.createClass({
onUpdate: function(evt) {
this.props.onChange(evt);
}
render: function(){
return(
<input type="text" onChange={this.onUpdate} value={this.props.value}/>
)
}
});
var Options = React.createClass({
getInitialState: function(){
return{
name: ''
}
},
render: function(){
return (
<div>
Name: <Name onChange={this.updateName} value={this.state.name} />
</div>
)
},
updateName: function(evt){
this.setState({
name: evt.target.value
});
}
});
Component Communication in React
Refer this link to know what are the ways to communicate between React components.
First of all I'm totally new to react so I'm not sure if my code is already written the "react way".
So far I've created a couple of react classes which render a Bootstrap Modal. To set the initial states I call an Ajax function within the componentsDidMount function. This works fine until I try to insert plain HTML into the modal body.
The server request works fine and I get plain HTML code in my this.state.data.content but if I try to insert this into the modal body I receive following error:
Error: Invariant Violation: Objects are not valid as a React child (found: object with keys {__html}). If you meant to render a collection of children, use an array instead or wrap the object using createFragment(object) from the React add-ons.
Does anyone know how to fix this? Am I even doing the right thing here?
Thanks!
<script type="text/babel">
var Modal = ReactBootstrap.Modal;
var Button = ReactBootstrap.Button;
var ButtonToolbar = ReactBootstrap.ButtonToolbar;
var L5fmHeaderButton = React.createClass({
render: function() {
var iconClass = "glyphicon " + this.props.buttonIcon;
return(
<button onClick={this.props.onClick} className="lfm-Modal-Button">
<span className={iconClass} aria-hidden="true"></span>
{this.props.buttonText}
</button>
);
}
});
var L5fmModalBody = React.createClass({
rawMarkup: function() {
return { __html: this.props.content };
},
render: function() {
return(
<Modal.Body>
dangerouslySetInnerHTML={this.rawMarkup()}
</Modal.Body>
);
}
});
var L5fmModal = React.createClass({
getInitialState : function() {
return {
data : []
};
},
componentDidMount: function() {
$.ajax({
url: 'L5fm/setInitialState',
dataType: 'json',
cache: false,
success: function(data) {
this.setState({data: data});
console.log(data);
console.log(this.state.data);
}.bind(this),
error: function(xhr, status, err) {
console.error(this.props.url, status, err.toString());
}.bind(this)
});
},
changeDirectory : function() {
if (this.state.privateDir) {
this.setState({privateDir: false});
}
else {
this.setState({privateDir: true});
}
},
render: function() {
if(this.state.data.privateDir) {
var browseIcon = "glyphicon-folder-open";
var browseText = "browse all files";
}
else {
var browseIcon = "glyphicon-briefcase";
var browseText = "browse private files";
}
return(
<Modal {...this.props} bsSize="large" aria-labelledby="contained-modal-title-lg">
<Modal.Header closeButton>
<div className="header-button-group">
<L5fmHeaderButton buttonIcon="glyphicon-cloud-upload" buttonText="upload" />
<L5fmHeaderButton buttonIcon="glyphicon-list" buttonText="list View" />
<L5fmHeaderButton onClick={this.changeDirectory} buttonIcon={browseIcon} buttonText={browseText} />
</div>
</Modal.Header>
<L5fmModalBody content={this.state.data.content}/>
</Modal>
);
}
});
var App = React.createClass({
getInitialState: function() {
return { lgShow: false };
},
render: function() {
let lgClose = () => this.setState({ lgShow: false });
return (
<ButtonToolbar>
<Button bsStyle="primary" onClick={()=>this.setState({ lgShow: true })}>
Launch large demo modal
</Button>
<L5fmModal show={this.state.lgShow} onHide={lgClose} />
</ButtonToolbar>
);
}
});
ReactDOM.render(<App />, document.getElementById("modal"));
</script>
Well, as it seems, you are missing a div-tag where you wish to render your raw html
considering changing the Modal.Body code like this
var L5fmModalBody = React.createClass({
rawMarkup: function() {
return { __html: this.props.content };
},
render: function() {
return(
<Modal.Body>
<div dangerouslySetInnerHTML={createMarkup()} />
</Modal.Body>
);
}
});
otherwise the rendering gets broken because your markup cannot really be set as a child on the Modal.Body element
The following code for data binding:
var Text = React.createClass({
getInitialState: function(){
return {
pageName: this.props.pageName,
url: this.props.pageName,
}
},
handleChange: function(event){
var pageName = event.target.value;
var url = event.target.value.toLowerCase();
this.setState({
pageName: pageName,
url: url,
});
},
render: function() {
return (
<div>
pageName: <input ref="pageName" onChange={this.handleChange} value={this.state.pageName}/><br/>
url: <input ref="url" onChange={this.handleChange} value={this.state.url}/><br/>
</div>);
}
});
React.render(<Text pageName="name" />, document.body);
A live demo can be see here. However, being that React re-renders after every input, the toLowerCase() function only picks up on the last letter. How would I make it so that it remembers the previous state(not looking for a slice()/splice() workaround, if possible). Thanks in advance!
You could add an id to the inputs to be able to determine where the input came from when handleChange is run. And then make sure that all input into url is always translated to Lowercase when you update pageName. E.g.
var Text = React.createClass({
getInitialState: function(){
return {
pageName: this.props.pageName,
url: this.props.pageName,
}
},
handleChange: function(event){
var pageName = event.target.value;
// ADDED EXTRA LINE HERE
pageName = (event.target.id == "url") ? pageName.toLowerCase() : pageName;
var url = event.target.value.toLowerCase();
this.setState({
pageName: pageName,
url: url,
});
},
render: function() {
return (
<div>
pageName: <input ref="pageName" onChange={this.handleChange} value={this.state.pageName}/><br/>
url: <input ref="url" id="url"onChange={this.handleChange} value={this.state.url}/><br/>
</div>);
}
});
React.render(<Text pageName="name" />, document.body);
You CANNOT however do two-way binding between both fields AND maintain all CAPS typed in name AND transform url to lowercase.
I want to have a react element on click execute another function from another js file which involves GET requests. How would I go about doing that.
React code:
/** #jsx React.DOM */
var SearchExample = React.createClass({
getInitialState: function(){
return { searchString: ' ' };
},
handleClick: function(event){
// do stuff in another file
},
handleChange: function(e){
this.setState({searchString:e.target.value});
},
render: function() {
var libraries = this.props.items,
searchString = this.state.searchString.trim().toLowerCase();
if(searchString.length > 0){
// We are searching. Filter the results.
libraries = libraries.filter(function(l){
return l.name.toLowerCase().match( searchString );
});
}
else
{
libraries = libraries.filter(function(l){
return l.popular.toLowerCase().match('true');
});
}
return <div>
<input type="text" value={this.state.searchString} onChange={this.handleChange} placeholder="What are you interested in..." />
<ul onClick={this.handleClick}>
{ libraries.map(function(l){
return <li key={l.name}>{l.name} </li>
})}
</ul>
</div>;
}
});
var libraries = [
{ name: 'Technology', popular: 'true'},
{ name: 'Fishing', popular: 'true'},
{ name: 'School', popular: 'true'},
{ name: 'Camping', popular: 'true'},
];
// Render the SearchExample component on the page
React.render(
<SearchExample items={ libraries } />,
document.getElementById('sidebar')
);
Currently the other JS code is in an html file, but I can change that later.
Pass that function as a prop to SearchExample class
AnotherFile.jsx
var HandleSearch = React.createClass({
handleSearch: function(a) {
//your code here
},
render: function() {
return <SearchExample handleClickOnSearch={this.handleSearch} items={ libraries } />
}
});
search example file
var SearchExample = React.createClass({
getInitialState: function(){
return { searchString: ' ' };
},
handleClick: function(event){
this.props.handleClickOnSearch(this.state.searchString);
},
handleChange: function(e){
this.setState({searchString:e.target.value});
},
render: function() {
var libraries = this.props.items,
searchString = this.state.searchString.trim().toLowerCase();
if(searchString.length > 0){
// We are searching. Filter the results.
libraries = libraries.filter(function(l){
return l.name.toLowerCase().match( searchString );
});
}
else
{
libraries = libraries.filter(function(l){
return l.popular.toLowerCase().match('true');
});
}
return <div>
<input type="text" value={this.state.searchString} onChange={this.handleChange} placeholder="What are you interested in..." />
<ul onClick={this.handleClick}>
{ libraries.map(function(l){
return <li key={l.name}>{l.name} </li>
})}
</ul>
</div>;
}
});
var libraries = [
{ name: 'Technology', popular: 'true'},
{ name: 'Fishing', popular: 'true'},
{ name: 'School', popular: 'true'},
{ name: 'Camping', popular: 'true'},
];
// Render the SearchExample component on the page
React.render(
<HandleSearch />,
document.getElementById('sidebar')
);
I have a searchForm component that renders a searchResult component. When the searchForm gets the results, it should pass the state to the result's state.
This where I fail.
var SearchForm = React.createClass({
getInitialState: function () {
return {
golden_record: {}
}
},
handleSearchSubmit: function (search_param) {
$.ajax({
url: this.props.url_variation,
type: 'GET',
data: search_param,
success: function (data) {
this.setState(
{
...
}
);
}.bind(this),
});
$.ajax({
url: this.props.url_golden,
type: 'GET',
data: search_param,
success: function (data) {
var golden_record = {
'site': data.sites[0].name,
'country': data.sites[0].country,
};
this.setState({'golden_record': golden_record});
}.bind(this),
})
},
render: function () {
return (
<div className="searchResult">
<SearchResult
golden_record={this.state.golden_record}
/>
</div>
);
}
});
SearchResult:
As you can see I am passing the golden_record as a property to the SearchResult. Inside SearchResult, when I set value of <input /> to the property this.props.golden_record['site'], the input is fixed to that value. But I want to set value rather to this.state.site so that I can change it afterwards, if I wanted to. So I don't know how to copy the read-only value of the prop to the state.
<input type="text" className="form-control" placeholder="Facility name" name="facilityName" onChange={this.onSiteChanged} value={this.props.golden_record['site']} ref="facilityName"></input>
Any suggestions please?
In your SearchResult component, you could set your state in componentWillReceiveProps:
var SearchResult = React.createClass({
...
getInitialState: function(){
return {
site: ''
}
},
componentDidMount: function(){
this.setState({ site: this.props.golden_record.site });
},
componentWillReceiveProps: function(newProps){
this.setState({ site: newProps.golden_record.site });
},
render: function(){
return <input type="text" className="form-control" placeholder="Facility name" name="facilityName" onChange={this.onSiteChanged} value={this.state.site} ref="facilityName"></input>
}
});