reactjs - reactjs在重新渲染父组件时弹出打开和关闭
问题描述
我正在尝试使用 reactjs 和 signalR (.netCore) 模拟 Trello 板。我创建了带有卡片列表的板,每个卡片项目都有弹出的卡片详细信息。当用户点击卡片标题时,弹出卡片的详细信息。我正在使用signalR(Websocket)通过侦听一个事件来使多用户在同一个板上进行交互,该事件在任何用户更改卡时重新呈现整个板。问题发生在以下情况:例如,用户 A 正在打开任务 1 的弹出模式,而用户 B 正在将任务 2 从待办事项卡片列表拖到正在进行的卡片列表中。当该操作发生时,弹出关闭并再次打开,因为整个 trello 板根据每个用户正在收听的事件重新呈现。如何通过弹出窗口解决打开关闭问题并保持打开状态' s?? 如果逻辑错误,请随时通知我!
注意:我将 react-beautiful-dnd 包用于拖放功能。
特雷洛板
<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 >
);
}
特雷罗列表
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>
)
};
特雷罗卡
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>
)
卡片详情组件
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 >
);
}
解决方案
推荐阅读
- python - 在实用程序函数中使用 Django request.session
- video-streaming - HTML5 视频无法在 IE11 或 Edge 中播放
- angular - 为 web 和 ionic 应用程序设置不同的“click_action”
- css - 如何在xamarin导航栏顶部制作两个按钮
- html - 在浏览器中将页面缩放到最小时出现文本问题
- entity-framework - Azure 移动应用和 Xamarin 尝试将 1:1 相关实体插入数据库
- javascript - 如何使用 JavaScript 上传到 CatBox?
- c - 指南针传感器没有给出正确的值
- javascript - NodeJs:错误 401(未经授权)我正在使用 passport-jwt
- java - Click时如何在显示器内滚动Horizontal Scrollview的项目?