Reacht 3 different cards next to each other - reactjs

I am new in React and have a problem with my cards here. I want to show 3 cards next to each other but I get 3 same cards. In bootstrap react I Found this loop to show cards next to each other but because I am looping my cars in const cards I get now 3 same cards next to each other.
I have tried using React bootstrap cards but none of them worked.
If anyone knows how I can fix my issue it would be a great help!
Here is my code:
const cards = hasLoaded ? (
<>
{cars.results.length ? (
<InfiniteScroll
children={cars.results.map((car) => (
<Car2 key={car.id} {...car} setCars={setCars} />
))}
dataLength={cars.results.length}
loader={<Asset spinner />}
hasMore={!!cars.next}
next={() => fetchMoreData(cars, setCars)}
/>
) : (
<Container className={appStyles.Content}>
<Asset src={NoResults} message={message} />
</Container>
)}
</>
) : (
<Container className={appStyles.Content}>
<Asset spinner />
</Container>
);
return (
<Container>
<Row className="h-100">
<Col className="py-2 p-0 p-lg-2" lg={8}>
<PopularProfiles mobile />
<i className={`fas fa-search ${styles.SearchIcon}`} />
<Form
className={styles.SearchBar}
onSubmit={(event) => event.preventDefault()}
>
<Form.Control
value={query}
onChange={(event) => setQuery(event.target.value)}
type="text"
className="mr-sm-2"
placeholder="Search posts"
/>
</Form>
</Col>
</Row>
<Row>
{Array.from({ length: 3 }).map((_, idx) => (
<Col md={3}>{cards}</Col>
))}
<Col md={3} className="d-none d-lg-block p-0 p-lg-2">
<PopularProfiles />
</Col>
</Row>
</Container>
);

Related

React: how print conditionally

I need to return conditionally a <Row> or </Row> if an index is 3 or multiple.
{
companyConfiguration.map((item, index) => {
return (
// here
{index%3===0 && <Row>}
<Col>
<FormComponent
key={index}
field={item}
onChange={handleChange}
currentItem={{}}
/>
</Col>
// here
{index%3===0 && </Row>}
)
})
}
But I get Unexpected token, expected ","
Edit:
I need to close after third element, and reopen it at fourth.
Examples given doesn't work unfortunately.
Must be a thing similar to
return (
<>
{
(index % 3 == 0) ?
<Row>
<Col>
<p>{index}</p>
<FormComponent
key={index}
field={item}
onChange={handleChange}
currentItem={{}}
/>
</Col>
:
<>
<Col>
<p>{index}</p>
<FormComponent
key={index}
field={item}
onChange={handleChange}
currentItem={{}}
/>
</Col>
</Row>
</>
}
</>
)
This is not the correct approach. You should wrap all the related components inside your tenary operator, so the correct approach would be
{index % 3 === 0 && (
<Row>
<Col>
<FormComponent
key={index}
field={item}
onChange={handleChange}
currentItem={{}}
/>
</Col>
</Row>
)
}
This is not e.g. like java scriptlets where you add a tag or html in general according to a variable's value - so you specify if a start tag and an end tag should be rendered at html page - so {index%3===0 && </Row>} is not correct.
also, you need to add fragments<> //some code</> to your code
{
companyConfiguration.map((item, index) => {
return (
<>
{index % 3 === 0 && (
<Row>
<Col>
<FormComponent
key={index}
field={item}
onChange={handleChange}
currentItem={{}}
/>
</Col>
</Row>
)
}
</>
)
})
}
You can use it like this
{
companyConfiguration.map((item, index) => {
return (
<>
{
index%3 === 0 ? <Row>
<Col>
<FormComponent
key={index}
field={item}
onChange={handleChange}
currentItem={{}}
/>
</Col>
</Row> : <Col>
<FormComponent
key={index}
field={item}
onChange={handleChange}
currentItem={{}}
/>
</Col>
}
</>
)
})
}

Is there a way to get a React Bootsrap card to show one card per row dynamically on a small screen

I am trying to get react bootstrap cards to show only card per row when the screen is small but it shows a mix of one and three cards per row . Please help.....example code is below
return (
<Container className="align-middle g-0 bg-transparent">
<Card.Body>
<Row className="justify-content-center">
{
cards.map((card) => {
return (
<Col className="col-lg-3 col-md-6 col-sm-12 col-xs-12">
<CardComponent data={data} />
</Col>
)
})
}
</Row>
</Card.Body>
</Container>
)
Instead of using className use the Bootstrap default way of defying columns, otherwise it adds a default col class
return (
<div className="App">
<h1>Hello CodeSandbox</h1>
<h2>Start editing to see some magic happen!</h2>
<Container className="align-middle g-0 bg-transparent">
<Card.Body>
<Row className="justify-content-center">
{cards.map((card) => (
<Col xs='12' md='6' lg='3'>
{card}
</Col>
))}
</Row>
</Card.Body>
</Container>
</div>
);

reactjs pop up opened and closed while re-rendering the parent component

I am trying to simulate the Trello board, with reactjs and signalR (.netCore).
I created the board with list of cards and each card item has card details which is a pop up.
that card details pop up opens when the user clicks on the card title. I am using signalR (Websocket) to make multiusers interact within the same board by listening to an event which re-render the whole board when any user change a card.
The issue happens when :
User A is Opening the pop up modal for task 1 and user B is dragging task 2 from todo card list to the in progress card list for example.
when that action happened the pop up close and open again as the whole trello board was rerendered based on the event that each user is listening to.
How can I fix that opening closing issue with the pop up an keep it open as it's ??
and if the logic is wrong please feel free to inform me!
note: I am using react-beautiful-dnd package for the drag and drop feature.
Trello Board
<DragDropContext
onDragEnd={(result) => {
ondragend(result);
}}
>
<div className="App">
<div>
{
sprintLoading ?
sprints.map((card, index) => (
// our sprints
<TrelloList
sprintType={card.sprintType}
index={index}
listId={card.sprintId}
sprintSchemaId={card.sprintSchemaId}
key={card.sprintId}
title={card.sprintName}
cards={card.tasks}
/>
))
: null
}
</DragDropContext >
);
}
Trello List
useEffect(async () => {
}, [tasks, socketState, trelloRerender]);
return (
<Droppable droppableId={String(listId)} >
{(provided) => (
<div
{...provided.droppableProps}
ref={provided.innerRef}
style={styles.container}>
<h4>{title}</h4>
{cards ? cards.map((card, index) =>
(
// our tasks
<TrelloCard
sprintType={sprintType}
listId={listId}
index={index}
cardId={card.taskId}
key={card.taskId}
text={card.taskDescription}
projectId={card.projectId}
userId={card.userId}
sprintId={card.sprintId}
sprintSchemaId={card.sprintSchemaId}
title={card.taskName}
schemaId={card.sprintSchemaId}
groupId={card.groupId}
taskStatus={card.taskStatus}
userName={card.user ? card.user.userName : ''}
taskCreatedDate={card.taskCreatedDate}
taskDueDate={card.taskDueDate}
comments={card.comments}
/>
)) : null}
{provided.placeholder}
</div>
)}
</Droppable>
)
};
Trello card
const { showTaskDetails, setShowTaskDetails } = useContext(ShowTaskDetailsContext);
useEffect(async () => {
await axios.get(`${BACKEND_URL}/tasks/${cardId}`).then(res => {
console.log(res.data.comments);
setCurrentTaskComments(res.data.comments)
console.log(currentTaskComments);
});
}, [rerenderForComments]);
useEffect(async () => {
const sprintId = location.pathname.split('/')[2];
setRerenderforCards(false);
setSprintId(sprintId);
setIsRolledback(false);
await fetchObject(`${BACKEND_URL}/sprintschemas/${sprintSchemaId}`)
.then(res => {
if (res.sprintTaskRollback !== null) {
setIsRolledback(true);
}
})
.catch(err => console.log(err));
}, []);
const handleShowTaskDetails = () => setShowTaskDetails(true);
const handleCloseTaskDetails = () => setShowTaskDetails(false);
return (
<Draggable draggableId={String(cardId)} index={index} key={cardId} >
{provided => (
// as provided.innerdiv need to refer to an action DOM node and card is a material-ui node
<div
ref={provided.innerRef}
{...provided.draggableProps}
{...provided.dragHandleProps} >
<Card style={styles.cardContainer} >
{/* testing generic hooks */}
<CardContent>
<Typography component={'div'}
gutterBottom>
<span
// href={`/loboard/${sprintId}`}
style={{ display: "block", fontWeight: "bold" }}
onClick={handleShowTaskDetails}
>
{title}
</span>
<TrelloCardDetails
showTaskDetails={showTaskDetails}
handleCloseTaskDetails={handleCloseTaskDetails}
title={title}
description={text}
comments={currentTaskComments}
assignto={userName}
cardId={cardId}
handleDropDownchanged={handleDropDownchanged}
handleMarkCompleted={handleMarkCompleted}
markCompletedBtnTxt={markCompletedBtnTxt}
markBtnStyle={markBtnStyle}
userId={userId}
setComments={setCurrentTaskComments}
rerenderForComments={rerenderForComments}
setRerenderForcommented={setRerenderForcommented}
/>
{/* onchange == move task to it's new list of cards */}
<Form.Group className="mt-2" controlId="exampleForm.ControlSelect2">
<Form.Row>
<Form.Label column="sm" sm={4}>Move to:</Form.Label>
<Col>
{/* adding default value to reset */}
<Form.Control size="sm" as="select"
onChange={handleDropDownchanged}
defaultValue={'select'}
>
<option disabled value="select">select status</option>
<option value="backlog" name='setBacklog'>backlog</option>
<option value="todo" name='setTodo'>todo</option>
<option value="inprogress" name='setInProgress'>inprogress</option>
<option value="done" name='setInProgress'>done</option>
</Form.Control>
</Col>
</Form.Row>
</Form.Group>
<Form.Group>
<Form.Row>
<Form.Label column="sm" sm={4}>assigned to:</Form.Label>
<Col>
<Form.Control
type="text"
disabled
value={userName} />
</Col>
</Form.Row>
</Form.Group>
<Row>
<Button className={markBtnStyle}
onClick=
{() =>
handleMarkCompleted(cardId)
}
style={{ display: "block" }}
>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" className="bi bi-check" viewBox="0 0 16 16">
<path d="M10.97 4.97a.75.75 0 0 1 1.07 1.05l-3.99 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425a.267.267 0 0 1 .02-.022z" />
</svg>
{markCompletedBtnTxt}
</Button>
</Row>
{/* <Row>
<Col> */}
<span className="text-sm float-right mt-2">
<small title="created at" className="text-muted d-block ">
<BsCalendar /> {taskCreatedDate.split('T')[0]}
</small>
</span>
</Typography>
</CardContent>
</Card>
</div>
)}
</Draggable>
)
Card details component
export const TrelloCardDetails = ({
showTaskDetails,
description,
comments,
title,
handleCloseTaskDetails
, assignto, cardId,
handleDropDownchanged,
handleMarkCompleted,
markBtnStyle,
markCompletedBtnTxt,
userId,
setComments, rerenderForComments,
setRerenderForcommented
}) => {
useEffect(() => {
console.log("card details")
}, [comments]);
return (
<div>
<Modal
show={showTaskDetails}
onHide={handleCloseTaskDetails}>
<Modal.Header closeButton>
<Modal.Title>{title}</Modal.Title>
</Modal.Header>
<Modal.Body>
<Form.Group className="mt-2" controlId="exampleForm.ControlSelect2">
<Form.Row>
<Form.Label column="sm" sm={4}>Move to:</Form.Label>
<Col>
{/* adding default value to reset */}
<Form.Control size="sm" as="select"
onChange={handleDropDownchanged}
defaultValue={'select'}
>
<option disabled value="select">select status</option>
<option value="backlog" name='setBacklog'>backlog</option>
<option value="todo" name='setTodo'>todo</option>
<option value="inprogress" name='setInProgress'>inprogress</option>
<option value="done" name='setInProgress'>done</option>
</Form.Control>
</Col>
</Form.Row>
</Form.Group>
<Form.Group>
<Form.Row>
<Form.Label column="sm" sm={4}>assigned to:</Form.Label>
<Col>
<Form.Control
type="text"
disabled
value={assignto} />
</Col>
</Form.Row>
</Form.Group>
<Form.Group>
<Form.Row>
<Form.Label column="sm" sm={4}>Description: </Form.Label>
<Col>
<Form.Control style={{ resize: 'none' }} as="textarea" value={description} disabled />
</Col>
</Form.Row>
</Form.Group>
<Row>
<Button
className={markBtnStyle}
onClick=
{() =>
handleMarkCompleted(cardId)
}
style={{ display: "block" }}
>
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" fill="currentColor" className="bi bi-check" viewBox="0 0 16 16">
<path d="M10.97 4.97a.75.75 0 0 1 1.07 1.05l-3.99 4.99a.75.75 0 0 1-1.08.02L4.324 8.384a.75.75 0 1 1 1.06-1.06l2.094 2.093 3.473-4.425a.267.267 0 0 1 .02-.022z" />
</svg>
{markCompletedBtnTxt}
</Button>
</Row>
{/* <div style={{marginTop:"20px", backgroundColor: "#e9ecef", opacity: "1", border: "1px solid #ced4da", borderRadius: "5px" }}> */}
<CommentList rerenderForComments={rerenderForComments} setRerenderForcommented={setRerenderForcommented} assignto={assignto} comments={comments} setComments={setComments} taskId={cardId} userId={userId} />
</Modal.Body>
<Modal.Footer>
<Button variant="secondary" onClick={handleCloseTaskDetails}>
Close
</Button>
<Button variant="primary" onClick={handleCloseTaskDetails}>
Save Changes
</Button>
</Modal.Footer>
</Modal>
</div >
);
}

How do I pass one string of an array each time a component is rendered?

This component renders four cards for top teams in a database, they are already sorted by highest scores; I need a <p> tag that displays either "1st", "2nd", "3rd", "4th" on each one. The current code displays "1st2nd3rd4th" in the <p> tag of each card.
const seed = ["1st", "2nd", "3rd", "4th"];
const place = seed.map((seed) => seed);
const TeamCard = ({data}) => {
return (
<TeamCardStyle>
{!data && (
<Spinner />
)}
{data && data.getGroupScores && (data.getGroupScores.slice(0, 4).map((group) => (
<Row>
<Col className="teamCard mt-2 mb-2">
<Row>
<p># {place}</p>
</Row>
<Row>
<Col className="hideSmall">
<img className="mouseOn" src="../images/group.png" />
<img className="mouseOff" src="../images/groupSelected.png" />
</Col>
</Row>
<p>{group.name}</p>
</Col>
</Row>
))
)}
</TeamCardStyle>
)
}
export default TeamCard;
Happy Hacking!
You can use index from map function to get the relevant element from seed array.
const seed = ["1st", "2nd", "3rd", "4th"];
const TeamCard = ({data}) => {
return (
<TeamCardStyle>
{!data && (
<Spinner />
)}
{data && data.getGroupScores && (
data.getGroupScores.slice(0, 4).map((group, index) => {
return (
<Row>
<Col className="teamCard mt-2 mb-2">
<Row>
<p># {seed[index]}</p>
</Row>
<Row>
<Col className="hideSmall">
<img className="mouseOn" src="../images/group.png" />
<img className="mouseOff" src="../images/groupSelected.png" />
</Col>
</Row>
<p>{group.name}</p>
</Col>
</Row>
)
})
)}
</TeamCardStyle>
)
}
export default TeamCard

in react-sortable-hoc Input wrapped loses focus when onChange is fired

i am using react-sortable-hoc in Model view,
But my component below, the input field loses focus after typing a character.
Focus on any row of Column 2 with onChange prop, type a 2-digit number (e.g. '20') on it and then lose focus after the 1st digit (e.g. after '2')
Why is this so?
Main Page Component
render() {
const SortableItem = sortableElement(({value,yourIndex}) =>{
return (
<Row xs="12">
<Col xs="1">
<FormGroup>
<DragHandle/>
</FormGroup>
</Col>
<Col xs="4">
<FormGroup>
{
this.state.MenuItems && this.state.MenuItems != null ?
<Select
options={this.state.MenuItems}
value={this.state.MenuItems.filter(option => option.value === value.menugroupsitemsitemid)}
onChange={this.handelItemSelectChange(yourIndex)} />
: <Select value={null} options={emptyVal} />
}
</FormGroup>
</Col>
<Col xs="2">
<FormGroup>
<Input
className="form-control-alternative text-right"
id="itemstepname"
placeholder="Price"
type="text"
name="itemsstepsitemsprice"
value={value.menugroupsitemsprice === undefined ? '0' : value.menugroupsitemsprice}
onChange={(e) => this.handelInputPrice(yourIndex,value.menugroupsitemsitemid,e)}
/>
</FormGroup>
</Col>
<Col xs="3">
<FormGroup>
{
this.state.TaxCode && this.state.TaxCode != null ?
<Select
placeholder="Tax"
options={this.state.TaxCode}
value={this.state.TaxCode.filter(option => option.value === value.menugroupsitemstaxcode)}
onChange={(newValue) => this.handelTaxSelectChange(yourIndex,value.menugroupsitemsitemid,newValue)} />
: <Select value={null} options={emptyVal} />
}
</FormGroup>
</Col>
<Col xs="2">
<FormGroup>
{
value.menugroupsitemsitemid ?
<span className="link-button" onClick={this.getItemSteps(value.menugroupsitemsitemid)}><i className="fa fa-edit mr-2 text-red" aria-hidden="true"></i></span> : null
}
{ this.state.menuGroupItem.length > 1 ?
<span className="link-button" onClick={(e) => this.DecreaseItem(yourIndex,value.menugroupsitemsitemid)}><i className="fa fa-minus-circle mr-2 text-red" aria-hidden="true"></i></span>
: null
}
{
this.state.menuGroupItem.length === yourIndex + 1 ?
<span className="link-button" onClick={this.IncrementItem}><i className="fa fa-plus-circle text-icon" aria-hidden="true"></i></span>
: null
}
</FormGroup>
</Col>
</Row>
)
});
const SortableItmList = sortableContainer(({items}) => {
return (
<Row>
<Col lg="12">
<FormGroup>
<label
className="form-control-label"
htmlFor="input-itemdescription"
>
Items
</label>
{items.map((value, index) => (
<SortableItem key={`item-${index}`} index={index} value={value} yourIndex={index} />
))}
</FormGroup>
</Col>
</Row>
)
});
return (
<Row>
<Modal
className="modal-dialog-centered"
isOpen={this.state.itemModal}
toggle={() => this.toggleModal("itemModal")}
>
<div className="modal-header">
<h2 className="modal-title" id="modal-title-default">
{this.state.menutypename}
</h2>
</div>
{this.state.itmModelError ? (
<div className="model-alert">
<Alert color="danger" isOpen={this.state.visible}>{this.state.itmModelError}</Alert>
</div>
) : null}
<div className="breadcrumb">
<li> <span className="menu-ol-list">{this.state.groupname}</span> </li>
</div>
<div className="modal-body">
<SortableItmList axis="y" helperClass="sortable-list-tab" lockAxis="y" distance={0} items={this.state.menuGroupItem} onSortEnd={this.onSortEnd.bind(this)} useDragHandle />
</div>
<div className="modal-footer">
<Button className="ml-auto" onClick={() => this.toggleModal("itemModal")} color="primary" type="button">
Go Back
</Button>
</div>
</Modal>
</Row>
)
}

Resources