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).
Related
I am trying to implement a component named CamViewMatrix in Vue.js. My requirement is to get the width of CamViewMatrix's parent inside itself (say in created() method of CamViewMatrix) so that I can make some calculations with it (there are some time-based charts that need to be made responsive which is not possible unless an initial value for width is in hand).
<div>
<div class='controller-wrapper'>
...
</div>
<CamViewMatrix v-bind:cameras='cams' />
</div>
I tried assigning an id to its parent and passed the same as a prop to CamViewMatrix, and attempts to getElementById, but it's not able to. Code given below:
<div id='parentid'>
<div class='controller-wrapper'>
...
</div>
<CamViewMatrix v-bind:cameras='cams' parentId='parentid' />
</div>
And inside CamViewMatrix component:
<script>
export default {
name: 'CamViewMatrix',
props: {
parentId: {
type: String,
required: true,
},
...
},
created() {
console.log(document.getElementById(this.parentId)); // 👈️ logs null
...
}
}
With the above code, I am not able to get the parent element (it's logging null).
Have also tried using ref and $parent, but was not able to. Kindly help me with this.
Thanks in advance.
created() is the wrong lifecycle hook to do that.
If you check the lifecycle diagram from the docs: https://v2.vuejs.org/v2/guide/instance.html#Lifecycle-Diagram
The element stuff is not yet done (rendered) and only the instance is created.
You most likely what to do that in mounted.
Next, you can access your component's parent via this.$parent and the element via this.$parent.$el.
Check out: https://v2.vuejs.org/v2/api/#Instance-Properties
If you want a specific element from parent, create a ref and access it like:
this.$parent.$refs.refNameYouAdded
If it's a Vue component, then it'd be a Vue instance so you need to access $el again:
this.$parent.$refs.refNameYouAdded.$el
otherwise if it's a HTML element, then no need to do that.
most of the time, the above answers work but sometimes if your parent component does things like moving elements somewhere else then it might not be accurate.
as mentioned in the comment, you can still access the correct parent element by doing:
this.$el.parentElement
I am a beginner in coding.
I have came across scenario in react where i can set my style dynamically based on condition.
style={{display:index > this.state.indexVal ? 'inline': 'none',}}
Can I use above concept for the getting current elements css one attribute value and changing other based on the same?
Expecting something like this
style={{display: currentElement.backgroundColor === 'red ? 'inline': 'none',}}
This is not a react way to perform checking like this and access elements directly. Since you want to "know" component state that can be changed (background color of some element in your case) - you should save it in component state (or pass to component props from parent element if you control this from parent component). Then you will be able to check this value in state or props.
You can user React Refs to access some element directly, but this is bad practice and you should do this only if you 100% can't do this with props/state:
https://reactjs.org/docs/refs-and-the-dom.html
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'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.
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);
}