首页 > 解决方案 > 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 >
    );
}

标签: reactjsreact-hookssignalrbootstrap-modalreact-dnd

解决方案


推荐阅读