How to test ref passed to a child component - reactjs

Need to test the React.createRef() part, but that is passed as a prop to the child component.
return (
<div id="excel">
<BuilderWrapper className="builderWrapper">
<Header name={name} desc={description} exportHandler={this.exportHandler} showData={this.showData} />
<BuilderNotification>
<Message infoMessage={cmsContent.messageOnExcelSheet} />
</BuilderNotification>
<BuilderSpreadsheet>
**<HotTable ref={this.hotTableComponent} {...this.setting} className={headerBoldCustom} />**
</BuilderSpreadsheet>
<HotFooter dimensions={dimensions} />
</BuilderWrapper>
</div>
);

Related

React conditionally render send prop to child

How can i conditionally send a prop to a child component. Ex:
<ProfilePage id={id} name={name} data={data} />
In the ProfilePage component data is optional and handles it accordingly. If data is empty, I dont want to send the prop to the component.
Theoretically like so:
<ProfilePage id={id} name={name} {if data then data={data}} />
I'm not sure of a terse way to make the syntax, but you can create an empty object, add the conditional props on there based on criteria, and then spread them on:
const additionalProps = {};
if (data) {
additionProps.data = data;
}
<ProfilePage id={id} name={name} {...additionalProps} />
In general, React encourages you to write components that accept null or undefined values for props and treat them as if they were not present.
<ProfilePage id={id} name={name} data={null} />
But if you absolutely must not pass data when its undefined, you can use a messy ternary.
<ProfilePage id={id} name={name} {...(data ? {data} : null)} />

How to hide multiple fields in react-admin ShowView?

I am trying to hide a set of fields based on the value of another field but the following will not display the conditional fields ever:
export const ServiceShow = (props) => (
<ShowController {...props}>
{controllerProps =>
<ShowView component="div" {...props} {...controllerProps}>
<TabbedShowLayout>
<Tab label="General">
{controllerProps.record && controllerProps.record.maintenance &&
controllerProps.record.maintenance.active &&
<>
<Alert severity="warning">Maintenance period active</Alert>
<DateField label="Maintenance Start" src="maintenance.start" />
<DateField label="Maintenance End" srvc="maintenance.end" />
<TextField label="Maintenance Message" source="maintenance.msg" />
</>
}
</Tab>
</TabbedShowLayout>
</ShowView>
}
</ShowController>
);
The <Alert> is displayed just fine, but the Field components are not. I'm very new to React so probably a simple thing.
Note:If I put a single <TextField> as the conditional output then it will work but anything inside a React.Fragment or <div> for example, it doesn't work.
The reason why Alert shows up and Fields not is because Fields require addtional props passed by react-admin direct parent, in that case, the Tab. <> should pass such props too, but looks like it's not. And thats why a single <TextField> as child renders correctly
You can create a component that pass the props downstream to childs.
export const ServiceShow = (props) => (
<ShowController {...props}>
{controllerProps =>
<ShowView component="div" {...props} {...controllerProps}>
<TabbedShowLayout>
<Tab label="General">
<Maintenance/>
</Tab>
</TabbedShowLayout>
</ShowView>
}
</ShowController>
);
const Maintenance = props => (
{props.record && props.record.maintenance && props.record.maintenance.active &&
<>
<Alert {...props} severity="warning">Maintenance period active</Alert>
<DateField {...props} label="Maintenance Start" src="maintenance.start" />
<DateField {...props} label="Maintenance End" srvc="maintenance.end" />
<TextField {...props}label="Maintenance Message" source="maintenance.msg" />
</>
}
)

How to add as attribute and get React Konva Element ID

I would like to know how to add an ID to an element and retrieve it similarly to e.target.getAttribute("id") for DOM elements. One thing to note is that the elements are based on an array that is part of the parent component. In order for the elements to render based on the parent's array, I added the and at parent component while and are at the child's. In short, it is structured this way.
Parent Class:
<div class="designScreen" onMouseDown={this.activateRouteTrigger} onMouseUp={this.deactivateRouteTrigger} onMouseMove={this.updateRoutePosition} >
<Stage
width={900}
height={700}>
<Layer>
{
this.state.trends.map((el) => {
return <Content id={el.id}
element={el.element}
color={el.color}
title={el.title}
type={el.type}
visibilityStatus={el.visibilityStatus}
selectType={this.selectType}
parentCallback = {this.selectDestinations}
selectedDestinationID = {this.state.selectedDestinationID}
destinations={this.state.destinations}
parentCallbackColor = {this.changeColorSelector}
timerString={this.state.timerString}
/>
})
}
</Layer>
</Stage>
</div>
Child Class:
render(){
const ex1= <Group >
<Rect name="name" onClick={this.selectedRouteID} width={10} height={10} draggable={true} fill="green"></Rect>
<Arrow id={`${this.props.element} content`} onClick={this.selectedRouteID} points={[700,300,200,300]} pointerLength={20} zIndex={5} draggable="true"
pointerWidth={20} fill={`${this.props.color}`} stroke={`${this.props.color}`} strokeWidth={4} />
</Group>
const ex2=
<Arrow points={[100,300,600,300]} pointerLength={20} zIndex={5} draggable="true"
pointerWidth={20} fill={`${this.props.color}`} stroke={`${this.props.color}`} strokeWidth={4} />
return(
this.props.element==="line" ? ex1 : ex2
)
}
}
I solved it, use e.target.getAttrs().fill, to get fill and replace it for other attributes

Getting warning about unique "key" when trying to import ReactCSSTransitionGroup into react app

I hope somebody could shed some light into this issue. After many attempts, I was able to import ReactCSSTransitionGroup into my react app correctly. Now I'm getting the following warning and my transition is not working.
Warning: Each child in an array or iterator should have a unique "key" prop.
I wrapped my component in the main App.js file with the ReactCSSTransitionGroup element like this.
return (
<div className="container">
<Navigation />
<div className="app-items-container">
{
this.state.notes.map((note) => {
return(
<ReactCSSTransitionGroup {...transitionOptions}>
<Note noteContent={note.noteContent}
noteId={note.id}
key={note.id}
removeNote={this.removeNote} />
</ReactCSSTransitionGroup>
)
})
}
</div>
<Form addNote={this.addNote} />
</div>
);
My component already has a key passed to it. Where should I apply the key?
I don't think you want the ReactCSSTransitionGroup inside the .map function. It should be outside and ReactCSSTransitionGroup will add it's magic to each of it's children (your Note component).
It works by adding additional lifecycle methods to 'each' of it's children as they are added/removed from the DOM. So there is no need to wrap each of the Note components with ReactCSSTransitionGroup, it should simply have all the Notes as it's children.
The key warning is because ReactCSSTransitionGroup will wrap it's children in a span. When in the .map loop, react will see something like the following:
<span> <Note key={note.id} /> </span>
<span> <Note key={note.id} /> </span>
<span> <Note key={note.id} /> </span>
React will want each of the spans to have a unique key, the child Note key will be ignored.
Moving it outside the map will give you this:
<span>
<Note key={note.id} />
<Note key={note.id} />
<Note key={note.id} />
</span>
And React will be happy as each Note has a key.
Try the following:
return (
<div className="container">
<Navigation />
<div className="app-items-container">
<ReactCSSTransitionGroup {...transitionOptions}>
{this.state.notes.map((note) => {
return(
<Note noteContent={note.noteContent}
noteId={note.id}
key={note.id}
removeNote={this.removeNote} />
)
})
}
</ReactCSSTransitionGroup>
</div>
<Form addNote={this.addNote} />
</div>
);
most likely you should be adding a unique key on <ReactCSSTransitionGroup > as well, could you try the following please?
return (
<div className="container">
<Navigation />
<div className="app-items-container">
{
this.state.notes.map((i, note) => {
return(
<ReactCSSTransitionGroup key={i} {...transitionOptions}>
<Note noteContent={note.noteContent}
noteId={note.id}
key={note.id}
removeNote={this.removeNote} />
</ReactCSSTransitionGroup>
)
})
}
</div>
<Form addNote={this.addNote} />
</div>
);
also, what micposso said makes sense, so it would be nice if you could make sure that node.id is indeed always unique.

What to do if your submit is outside of redux-form

What to do if your submit is outside of form?
Example:
<Root>
<Header>
<Button label={'SAVE'} onClick={this.clickHandler}/> // <-- My handler for save form data
<Button label={'DELETE'} />
</Header>
<Form onSubmit={this.handleSubmit} fields={fieldsList} /> // <-- My form
<Root />
Should I be using getValues?
From v4.2.0 you can add a ref prop to your form component and call submit() on that ref. See example at http://redux-form.com/5.3.1/#/examples/submit-from-parent
clickHandler() {
this.refs.myForm.submit()
}
<Root>
<Header>
<Button label={'SAVE'} onClick={this.clickHandler}/>
<Button label={'DELETE'} />
</Header>
<Form ref="myForm" fields={fieldsList} />
</Root>

Resources