I'm trying to understand how I can do the following flow in React
page load
ajaxA()
-return dataA
-render dropdown HTML
-ajaxB(dataA)
-return dataB
-render chart HTML
handleDropdownChange()
-ajaxB()
-return dataB
-render chart HTML
I have it split out into two components
a top section with controls (ajaxA returns data to build some dropdowns.
a couple of chart below. When one of the dropdowns in the top part changes, then the chart should update.
Should ParentApp contain all methods for updating the charts and data related to child components, passing both in as props, eg:
handleControlChange (event) {
this.setState(selectedOption: event.target.value)
},
render () {
return (
<ParentApp>
<Controls
handleControlChange={this.handleControlChange} />
<Chart />
</ParentApp>
)
}
or should that functionality live within the Controls component? The second way seems more reasonable to me but since Controls and Chart are siblings I'm not sure how I can pass data to Chart when there is a change within`Controls. As I understand it data only flows from parents to children in React. It seems like ParentApp would soon contain basically all the methods needed by its children components which kind of seems it goes against keeping components modular.
Where should I store my data and my methods to interact with it?
In principle React only lift the state up when this state must be shared between siblings and/or parent, when a child component doesn't need to send its state to parent or siblings it can have its own state and no lifting up is needed.
But practically speaking most apps will have state in central place at parent component, there are even libraries for central states like Redux , that being said we didn't lose modularity in any way because state is only part of the story, for example spliting the app into components will give you modularity in rendering, also because child components takes props you can reuse the same component in multiple places with different props to control its appearance almost the same way you change the appearance of an <a> link by just applying a class.
Related
in my parent render function, I am rendering a list of form inputs. They can be number, slider, text, etc, and for each, I have a custom Vue component, i.e. FormInputSlider. I receive some data from an API, and then have an array of these different inputs to render. Doing a huge if/else block in my parent's render code seems unmaintainable, so what is the best/standard way of rendering a FormInputSlider component when I encounter a "form-input-slider" in the list iteration? I'm coming from a React understanding of the world for what it's worth.
If you've the component names, you could just use the built-in component tag to render the component dynamically :
<component :is="dynamicName" />
instead of :
<template v-if="dynamicName==='abc'">
<abc/>
</template>
<template v-elseif="dynamicName==='xyz'">
<xyz/>
</template>
....
I'm writing a React application with a lot of modals (but only one ever active at a time with no nested modals), and I'm unsure of which of these two solutions is preferable when it comes to handling showing and hiding these modals:
Have a state boolean variable in the parent component that determines whether or not the modal should be shown. If this boolean variable is false, don't render the component. If it's true, render it. Allow the modal to influence this event via a passed in props callback it can leverage. Example snippets:
{ this.state.prompt === "makePW" ?
<MakePassword closeModal={this.closePWModal} /> :
null
}
Now, within the component, it is always visible and does not control its lifecycle. If it is being rendered then it is visible.
Just always show the component in the parent component, like so:
<MakePassword />
Then within the component itself handle its entire lifecycle. That is, the component will have a boolean state variable for its visibility. Some snippets for this approach:
<Modal open={this.state.open} onClose={this.closeModal}>
<Modal.Header>Header</Modal.Header>
<Modal.Content>Body</Modal.Content>
</Modal>
There are also hybrid approaches, and other solutions as well I'm sure.
Regardless, I suppose the essence of my question is wondering about the preferable solution for showing and hiding modals: is it to always render them and just toggle their visibility, or to actually toggle between adding and removing them from the DOM? And, should the modal itself generally control its lifecycle or should the parent?
i prefer 1st one but if you want to use the second , i would extend the makepassword component from PureComponent to optimize your component.
Instead of writing shouldComponentUpdate() by hand, you can inherit from React.PureComponent. It is equivalent to implementing shouldComponentUpdate() with a shallow comparison of current and previous props and state. - source react docs
class MakePassword extends React.PureComponent{
...
}
I think it depends on your application.
For example, React-Bootstrap modals stay in the DOM and that allows for nice in/out animations.
I’ve hit an interesting issue that doesn’t fit with Ember’s data down, actions up principle.
I have a code editor component (code-editor) sat inside a parent component (request-editor). There's a method on the editor component to insert a string at the current cursor position. The parent component includes some buttons to insert things into the editor (e.g. the current date).
I think I'm right in separating the buttons from the editor because the editor is used elsewhere without these buttons.
It obviously doesn't make sense to use a bound variable for this use-case because it's not really data, it's wanting to perform an action. I.e. {{code-editor insertText=insertText}} makes no sense.
How is it possible to effectively call codeEditorChildComponent.insert() from the parent component? I appreciate it will probably involve coupling them together but they have to be coupled for it to work anyway. The parent component is composed of the child components already.
All communications should be done using actions.
I think below is a good way. And you have code_editor property in request-editor component then could send action to code-editor component.
request-editor.hbs
{{code-editor owner=this}}
request-editor.js
actions:{
setChild(child){
this.set('code_editor', child);
}
}
code-editor.js
didInsertElement(){
this._super(...arguments);
this.get('owner').send('setChild', this);
}
I built a simplistic tab container in ReactJS using the idea that the container component keeps in its state an integer index denoting the tab pane to display and then renders only the child (from the this.props.children array) that is found at that index position.
The gist of this approach was:
const TabContainer = React.createClass({
props: {
tabNames: React.PropTypes.arrayOf(React.PropTypes.string).isRequired
},
getInitialState: function() {
return {
activeIndex: 0
};
},
setTab: function(n) {
this.setState({activeIndex: n});
},
render: function render() {
const childToRender = this.props.children[this.state.activeIndex];
return (
<div className='tab-container'>
<Tabs
tabNames= {this.props.tabNames}
active = {this.state.active}
setTab = {this.setTab}
/>
<div className='tab-pane'>
{childToRender}
</div>
</div>
);
}
});
I.e. only the indexed child is selected and rendered (I've omitted for the sake of simplicity the code handling the edge case where this.props.children is not an Array).
I found out that this approach was unsatisfactory as when the user selected different tabs, the component corresponding to the pane to render was mounted and unmounted repeatedly and any state that the panes had could not be preserved.
Ultimately, I used an approach in which all children are rendered and all panes, except the selected one, are assigned a class hidden that is then used to style those panes as: display:none. When this later solution was used my panes remained mounted even after the user clicked through the various tabs and any state they had wasn't lost as the user cycled through the tabs.
My questions are:
was the initial approach (where only a specific child is rendered) an anti-pattern or was there some other mechanism I could have used to preserve the state of the individual panes or prevent them from being unmounted?
if the initial approach was indeed an anti-pattern how can that anti-pattern be expressed more generally?
I don't think the initial approach was an antipattern at all. Choosing whether or not to mount/unmount in your logic is just dependent on your circumstances. If you want state preserved, then don't unmount. If you want a fresh element, complete with a call to getInitialState, then unmounting is the right way to go.
As an easy counterexample, consider React-Router. The Router completely unmounts/remounts components on route change. And route changing is effectively just a higher order of tabbing.
But given the situation where you want state preserved, I think your solution is the proper one. You might want to take a look at material-ui, which does something very similar in their tabbing: https://github.com/callemall/material-ui/blob/master/src/Tabs/TabTemplate.js
I have a table within a bootstrap panel.
Something like this:
<Panel className='userPanel'>
<Table/>
</Panel>
Now I need to have a reference to Panel within Table. There can be a lot of tables/panels on one site the same time, so I don't want to use ids to use them with ReactDom.findDOMNode.... What is the best solution for this?
Edit:
I need a reference in the table because I use Facebooks datatable. These tables do have a static width/height so to make them fluid, I need to add a resize handler that checks the width and height of the parent to adjust.
What you are suggesting breaks the way that React encourages you to work. Components should be encapsulated, all the data they need should be passed to them as props. Every time you make calls out from a component you invalidate their referential transparency i.e. the output of a component (usually what is rendered) should be the result of the props passed to it.
Having said that, people use React in different ways (it even gives you setState to wreak havoc with purity) however, passing the actual DOM node to children is difficult as when they are instantiated their parents' DOM node does not exist.
I dont know the Facebook DataTable API so I can't really suggest a better way of restructuring your app, but it sounds like you just need a dynamic width/height to size the table so pass down a function to get that.
class Parent extends React.Component {
constructor( props ) {
super( props )
}
getDimensions() {
// Do some stuff here to return dimensions
return {
width: XXX,
height: XXX
}
}
render() {
<Parent ref="el">
<Table getDimension={ this.getDimensions } />
</Parent>
}
}
You still can't call this.props.setDimensions from within Table:render but you cant with the .parentNode solution anyway so I'm guessing you’re already rendering the table in componentDidMount (or later).