React mapping over the same array but rendering different output - arrays

I have a case where I need to map over the same array twice in my render method to render different properties of the objects in the array.
So, this is the case:
<Row>
<Column xs="12" md="6">
<Row>
<Column xs="12">
<Undertekst>
<FormattedMessage id="InfoPanel.PaymentDates" />
</Undertekst>
</Column>
</Row>
{getPeriods(payment.periods, periodsDates)}
</Column>
<Column xs="12" md="6">
<Row>
<Column xs="12">
<Undertekst>
<FormattedMessage id="InfoPanel.PaymentAmount" />
</Undertekst>
</Column>
</Row>
{getPeriods(payment.periods, amount)}
</Column>
</Row>
So, since I need to map over the same array in two places I have made a function that takes an array and a fuction which will render children element from the current object in the array.
const periodsDates = period => `${moment(period .from).format(DDMMYYYY_DATE_FORMAT)} - ${moment(period .to).format(DDMMYYYY_DATE_FORMAT)}`;
const amount= period => formatCurrency(period.amount);
const getPeriods = (periods, children) => periods.map(period => (
<Row>
<Column xs="12">
<Normaltekst>
{children(period )}
</Normaltekst>
</Column>
</Row>
));
I wonder if that is the way to go about this, or is there a better way to solve this, maybe with currying if possible?

You can build a new stateless component lets say you call it Periods with 2 props ( periods , data ).
This way you can even use it elsewhere.

Related

Parsing error: JSX element 'ValidatedForm' has no corresponding closing tag

I noticed that when I use more Rows and Cols to create a suitable UI for form validations, my validation does throw this error. The validation only captures data when it is within a Col tag .
It throws this error in my prettier terminal "JSX expressions must have one parent element". i.e the it must be within the Col tag
See the codes below for clarifications
<Row>
<Col sm={4}>
{loading ? (
<p>Loading...</p>
) : (
<ValidatedForm defaultValues={defaultValues()} onSubmit={saveEntity}> {!isNew ?
<ValidatedField name="id" required readOnly id="terminal-id" label="ID" validate={{ required: true }} /> : null}
</Col>
<Col sm={4}>
<ValidatedField
label="Stock Level Date"
id="terminal-stockLevelDate"
name="stockLevelDate"
data-cy="stockLevelDate"
type="date"
/>
<ValidatedField
label="Tank Threat Level"
id="terminal-tankThreatLevel"
name="tankThreatLevel"
data-cy="tankThreatLevel"
type="number"
/></Col>
</Row>
<Row>
<Col sm>
<ValidatedField
label="Low Pumpable Color"
id="terminal-lowPumpableColor"
name="lowPumpableColor"
data-cy="lowPumpableColor"
type="text"
/></ValidatedForm>
)}
</Col></Row>
Can anyone enlighten me on another way around this.. And besides the Validation form indeed has a closing tag but it is not within the same Col
There is no closing tag for the ValidatedForm in this line
<Col sm={4}>
<ValidatedForm defaultValues={defaultValues()} onSubmit={saveEntity}/>
</Col>
The tree structure here is also messed up, you might want to fix that
<Row>
<Col sm>
<ValidatedField
label="Low Pumpable Color"
id="terminal-lowPumpableColor"
name="lowPumpableColor"
data-cy="lowPumpableColor"
type="text"
/>
</Col></Row></ValidatedForm>

ANT Design Push Pull Confusion

I have two columns with setup like this:
<Row>
<Col xs={24} lg={12}>
<p>Column 1</p>
</Col>
<Col xs={24} lg={12}>
<p>Column 2</p>
</Col>
</Row>
How can I use push or pull from the ANT Design Doc to make Column 2 to be above Column 1 in smaller screen?
We can't push/pull on the xs column because each column takes up the full width. Instead we can put column 2 on top initially and change the order when the viewport is large. At the large breakpoint we can push Column 2 to the right and pull Column 1 to the left.
The Grid API allows us to pass objects containing props such as span, push, and pull for the breakpoint.
<Row>
<Col xs={24} lg={{span: 12, push: 12}}>
<p>Column 2</p>
</Col>
<Col xs={24} lg={{span: 12, pull: 12}}>
<p>Column 1</p>
</Col>
</Row>

hidden-xs-down is not working React bootstrap

I am trying to hide few columns on mobile screens but its not working for some reason. Here's my code:
<Row>
<Col className="col-md-2">Route Image</Col>
<Col className="col-md-3">
<Row>
<Col>Route Name</Col>
</Row>
<Row>
<Col>Route Location</Col>
</Row>
</Col>
<Col className="col-md-3 hidden-xs-down">Route Difficulty</Col>
<Col className="col-md-2 hidden-xs-down">Route Length</Col>
<Col className="col-md-2 hidden-xs-down">View Details</Col>
</Row>
Can someone please tell me what I am doing wrong?
Since Bootstrap v4.x, all .hidden- classes have been removed. You should use d-none .d-sm-block instead if you want to hide your element only on xs

Conditional alternating Parent tags in jsx

Use Case:
array.map((field, index) =>{
const Wrapper = index % 2 === 0 ? <RowWrapper> : <React.Fragment>
return (
<Wrapper>
<Col md={4}>
</Col>
<Col md={2}>
</Col>
</Wrapper>
);
})
Expected Output:
<RowWrapper>
<Col md={4}>
</Col>
<Col md={2}>
</Col>
<Col md={4}>
</Col>
<Col md={2}>
</Col>
</RowWrapper>
In the above scenario. Basically I want map to return an opening RowWrapper tag but not closing tag until I have mapped two fields.
Unfortunately, I don't believe that JSX can be made to behave in exactly this manner, in which closing tags are conditionally rendered. However, the output is still achievable if you get clever with your map callback:
array.map((field, index) =>{
if (index % 2 === 0) {
return (
<RowWrapper>
<Col md={6}>current content is {array[index]}</Col>
<Col md={6}>next index content is {array[index+1]}</Col>
</RowWrapper>
);
}
return null; // just skip if this isn't an even numbered index
})
I haven't tested that but something like that should accomplish the output you desire. Obviously you'd want to add checking for off-by-one type scenarios.

How can I call a component with a react button? [duplicate]

This question already has answers here:
onClick doesn't render new react component.
(5 answers)
Closed 3 years ago.
Sorry if this topic is probably a copy of another one, but I am still with some doubts and I could not solve reading this related topics:
onClick doesn't render new react component.
How can I call my 'Survey' component from the react button, using onClick?
I am using "onClick={Survey}" but it is not working, there is another way to do it or it is something wrong with this kind of call.
class App extends Component {
render() {
return (
<div className="App">
<Container>
<Row>
<Col><ClientInformation /></Col>
</Row>
<Row>
<Col>1 of 2 </Col>
<Col>2 of 2</Col>
</Row>
<Row>
<Col><Button variant="outline-primary" size="lg" block>QR Code
</Button></Col>
<Col><Button variant="outline-success" size="lg" block onClick={Survey} >Survey</Button></Col>
</Row>
<Row>
<Col>1 of 2</Col>
<Col>2 of 2</Col>
</Row>
<Row>
<Col><Button variant="outline-warning" size="lg" block>Warning</Button></Col>
<Col><Button variant="outline-secondary" size="lg" block>Secondary</Button></Col>
</Row>
<Row>
<Col>1 of 2</Col>
<Col>2 of 2</Col>
</Row>
</Container>
</div>
</div>
);
}
}
export default App;
onClick is an event handler, it's a function that is called to do something... there does not exist any built-in functionality in React that would allow you to give a component directly to a function and expect it to know what to do with it and when.
What you'd need to do is store a piece of data in your state that you can use to conditionally render the component.
I noticed you tagged this question with react-router. If you're talking about how to provide a component for a certain route, you need to import their built-in Route, Switch and Link components and provide your own component as the component prop on the Route. They provide an example.
I think you are misunderstanding for the onClick handler.
it requires function not react component or object.
Please use this.
import Survay from './survay'; // use correct path of the survay component
class App extends Component {
state = {
display: false,
}
render() {
return (
<div className="App">
<Container>
<Row>
<Col><ClientInformation /></Col>
</Row>
<Row>
<Col>1 of 2 </Col>
<Col>2 of 2</Col>
</Row>
<Row>
<Col><Button variant="outline-primary" size="lg" block>QR Code
</Button></Col>
<Col><Button variant="outline-success" size="lg" block onClick={()=>{this.setState({display: true})} >Survey</Button></Col>
</Row>
<Row>
<Col>1 of 2</Col>
<Col>2 of 2</Col>
</Row>
<Row>
<Col><Button variant="outline-warning" size="lg" block>Warning</Button></Col>
<Col><Button variant="outline-secondary" size="lg" block>Secondary</Button></Col>
</Row>
<Row>
<Col>1 of 2</Col>
<Col>2 of 2</Col>
</Row>
{
display &&
<Survey/>
}
</Container>
</div>
</div>
);
}
}
export default App;
And then please add the style to set a proper position and displaying for your Survay component.

Resources