I am new to ReactJS and had been through some examples: flux-todo-mvc.
Since react keeps component in a tree structure and updates on state change.
How can I add a new child component (not bundled) at specific node of tree without page refresh?
More Description
Suppose component X can have three types of child: A, B and C. At first GET request it is always A so X -> A is rendered and to make it fast we did not include B and C. For example:
X = React.createClass({
render: function() {
return (
<A />
);
}
});
React.render( <X />, document.getElementById('_x') );
After this, with some change in state can we change child of X to B or C using AJAX request
You can write conditional logic inside your render function to set a variable to null or a component instance. And inject that inside the returned render JSX.
Such as:
render: function() {
var subComponent = null;
if (this.state.showSub) {
subComponent = <Child />;
}
return (
<div>{subComponent}</div>
);
}
Only way to do it with state changes in real time. Can't update the render code in real time without an actual refresh.
you can do something like this:
render: function() {
var child = function(){
if(this.state.ajax_result ==1) {return <B/>
else if(this.state.ajax_result ==2) {return <C/>}
else {return <A/>}
}
return ( {child} );
}
now outside of render, listen to your ajax calls. every time the state will change, your component will re-render
Related
My app has a feature toggle functionality that tells my UI whether or not a piece of UI should be rendered. I would like to create a Higher Order Component to conditionally render these types of components. In one scenario, I'm trying to conditionally render a list, but I'm running into this error:
ConditionalRender(...): A valid React element (or null) must be returned. You may have returned undefined, an array or some other invalid object.
This makes sense since I just am trying to render the children of this component. Here's what I've got so far:
https://jsfiddle.net/fmpeyton/cykmyabL/
var settings = { showHello: true, showGoodbye: false};
function ConditionalRender (props) {
var output = null;
if(props.shouldRender) output = props.children;
console.log(output);
// return (<li>{output}</li>); // This works, but isn't desired html structure
return ({output});
}
function App (props) {
return (
<ul>
<ConditionalRender shouldRender={props.settings.showHello}>
<li>Hello!</li>
</ConditionalRender>
<ConditionalRender shouldRender={props.settings.showGoodbye}>
<li>Goodbye...</li>
</ConditionalRender>
</ul>
);
}
ReactDOM.render(
<App settings={settings} />,
document.getElementById('container')
);
If I can help it, I would just like to render the children without any additional logic.This HOC would also handle more complex children down the line. Something like this:
<ConditionalRender shouldRender={props.settings.showHello}>
<div>
<p> blah blah blah</p>
<table>
<!-- ... -->
</table>
</div>
</ConditionalRender>
Any ideas?
Try this:
function App(props) {
return (
<ul>
{props.settings.showHello && <li>Hello!</li>}
{props.settings.showGoodbye && <li>Goodbye...</li>}
</ul>
);
}
P.S. Your code doesn't work because of this line:
return ({output});
Assuming you have es2015 support, it would be treated as object property shorthand. So it's the same as:
return {output: output};
which is not what React expects to get from the render method.
You could try this:
function ConditionalRender(props) {
if (props.shouldRender) {
// Make sure we have only a single child
return React.Children.only(props.children);
} else {
return null;
}
}
But this is not the simplest way. See more here.
P.P.S. Your ConditionalRender component is not what is called Higher-Order Component. According to the docs, HOC is a function that takes a component and returns a new component.
On my template js I have the following
updateBarTitle(title){
this.setState({barTItle:title});
}
render() {
const childrenWithProps = React.Children.map(this.props.children, function (child) {
var childProps = {
updateBarTitle: this.updateBarTitle.bind(this)
};
var childWithProps = React.cloneElement(child, childProps);
return childWithProps;
}, this);
And on the child I have.
componentDidUpdate(){
this.props.updateBarTitle('Users');
}
When testing out the app and once state changes my browser freezes for a long time then returns a Maximum call stack size exceeded Need some advice on what I'm doing wrong.
You're creating an infinite loop with the child componentDidUpdate() method. It calls updateBarTitle(), which calls setState(), which re-renders, which calls updateBarTitle() again...and so on.
If you want that logic in the componentDidUpdate() method where you have it, you need to add some condition so that it will only call once.
You could pass the current state of barTitle to the child as a prop and then do something like:
if(this.props.barTitle !== 'Users') {
this.props.updateBarTitle('Users');
}
To stop that loop from happening for example.
EDIT: To give a clearer example here is a DEMO of this to illustrate.
This is not a question as much "how to make this work" as much as it is a "was this the best way." Here's my code:
/**
* React Static Boilerplate
* https://github.com/koistya/react-static-boilerplate
* Copyright (c) Konstantin Tarkus (#koistya) | MIT license
*/
import React, { Component } from 'react';
// import './InputWidgetText.scss';
import ContentBlock from '../ContentBlock';
var i = 0;
var contentBlocks = [];
var ContentContainer = React.createClass({
addNewBlock: function(){
i++;
contentBlocks.push(<ContentBlock key={i} index={i}/>)
this.forceUpdate();
},
render: function(){
if (this.props.inputs) {
contentBlocks = this.props.inputs.map(function(item, index){
i++;
return(<ContentBlock key={index} index={index} content={item} />)
});
}
return (
<div>
{contentBlocks}
<button onClick={this.addNewBlock}>+</button>
</div>
)
}
});
export {ContentContainer as default};
The problem is that every so often on a refresh the props.inputs are not getting passed down to this component and throwing an error when I try to map undefined. So the simple solution is to put the map process in an if check for whether or not the props are there yet - is that actually the right way to handle this? My data is passed in via a reflux mixin on the parent. I just feel like there might be a more proper way to handle this. Thanks for the feedback!
May I strongly suggest you refactor your code to do away with the file variables i and contentBlocks.
The contentBlocks variable seems completely unnecessary, whilst your i variable should be part of the state. Whilst you're at it, give i a more meaningful name, e.g. blockCount.
getInitialState: function () {
return {
blockCount: 0
};
},
Then define your click event handler to modify the state:
addNewBlock: function () {
this.setState({
blockCount: this.state.blockCount + 1
});
},
Every time you call setState(), React will trigger a re-render. You should never need to call forceUpdate().
Finally, your render() function should return its content based SOLELY on this.props and this.state. That is, for any given props and state, the output will be predictable. Think of this.props and this.state as input parameters to the render() function. That is all render() can, or needs to, know about.
I won't try to write the render() function as I'm not sure exactly what you're trying to achieve with this component. But for a given this.props.input and this.state.blockCount (or whatever you choose to use as props and state) you should know exactly what you're outputting.
I know I haven't directly answered the question you put, but I hope this clarifies some React concepts.
I've got a React component hierarchy that looks a little like this:
var A = React.createClass({
render: function() {
/* stuff */
}
});
var B = React.createClass({
render: function() {
return dom.div(null, this.props.children);
}
});
var C = React.createClass({
render: function() {
return dom.div(null, B(null, A()));
}
});
Essentially, C passes an A element to B as a child, and B subsequently renders it.
Now I'm in a position where I want to update the A element but not B. It's unclear to me what the semantics of shouldComponentUpdate are in this case. If I implement a shouldComponentUpdate in B, do I need to consider whether or not my children should update? Is it impossible to update the child without updating it's immediate parent?
If you want to update A but not B, you should actually describe A behaviour in it's own component - for example, subscribe to some third-party source of truth (Store in terms of Flux architecture) in A's componentDidMount hook.
This is the only way - if A has no control on it's own flow, it will update only on B (exectly parent) render() call - which you can already control by B's (and \ or it's parents') shouldComponentUpdate.
I have just started to study ReactJS and have some questions. I was reading documentation here, but I can't find the answer I am looking for. Here is an example:
var Awesome = React.createClass({
getInitialState:function() {
return {
txt : ["1","2","3","4","5"],
isTrue : true
}
},
handleClick:function() {
this.setState({
isTrue : !this.state.isTrue
})
},
render:function() {
var changeStyle = {
display: this.state.isTrue ? "block" : "none"
};
var message = this.state.txt.map(function(oneMessage) {
return <SubChild change={changeStyle} txt={oneMessage}/>
});
return (
<div>
<button onClick={this.handleClick} >Click Me</button>
{message}
</div>
)
}
})
var SubChild = React.createClass({
render:function() {
return (
<div style={this.props.change}>
<h3>{this.props.txt}</h3>
</div>
)
}
})
React.render(<Awesome />, document.body)
Everything works fine, but I have some questions. As you can see I store my state inside a variable. Is this the best practice? How can I achieve the same result without variables inside render function or actually without states (I am trying to avoid state). Is this possible?
Here is my Fiddle
Why State Variables?
The idea of using state variables is to have changing / dynamic data, ie if anything about the component is changing, it should be defined as a state variable in the component so user interaction can result in change of this variable and a change in this variable causes the effected component to re-render.
Use of Properties
If some value is changed for each instance of the component and is uneffected by user interaction or component state change, it should be defined as a property so it can be assigned only once at instantiation.
In all cases, we cannot really avoid the use of variables inside the render