渲染组件未响应其道具更新

问题描述 投票:0回答:1

我正在创建与Trello类似的React App。在我们有项目的情况下,项目有电路板,电路板有列,列有任务等。默认情况下,只有包含其木板名称的条的Project应该可见-其余部分应该隐藏。而且,如果您单击带有板标题的栏,则该板的全部内容应该可见。另外,再次单击该栏时,它应该再次隐藏。我希望这很清楚。

问题是,我在一个组件(ProjectView)中绘制了带有板名的栏,其中包含许多子组件(Board),这些组件最终可以呈现每个板(BoardView)的内容。在ProjectView中,我有一张地图(visibilityMap),该地图将isHidden-boolean分配给电路板的名称。此映射中的对应值传递到每个Board组件的prop,而Board组件将其传递到BoardView,在其中它用于定义具有内容的div的属性值。另外,在ProjectView中,我有一个函数,可在单击适当的板子名称后更改地图中的适当布尔值。一切都呈现正确,我可以在日志中看到,单击木板名称后,visibilityMap中的特定值会更改,但不会更改特定木板内容的可见性。我为此花费了很多时间,并尝试了许多奇怪的事情,但我不知道出了什么问题。下面,我附上了所描述组件的代码和两个屏幕截图-单击“ board-name”之前和之后。

ProjectView

-几乎所有内容都在renderBoardimport React from 'react'; import {Button} from "react-bootstrap"; import TextField from '@material-ui/core/TextField'; import Dialog from '@material-ui/core/Dialog'; import DialogActions from '@material-ui/core/DialogActions'; import DialogContent from '@material-ui/core/DialogContent'; import DialogTitle from '@material-ui/core/DialogTitle'; import Board from "../controllers/Board"; import {PhotoshopPicker} from 'react-color'; require("../../styles/Project.css"); require("../../styles/Board.css"); class ProjectView extends React.Component { constructor(props) { super(props); this.state = { render: false, modalShow: false, modalAddShow: false, modalBoard: "", boardName: "", boardBackground: "orange", newName: "", newBackground: "", showAddBackground: false, showChangeBackground: false, pickedBackground: "orange", validate: true, visibilityMap: new Map() }; this.handleChange = this.handleChange.bind(this); } renderBoards = () => { if (this.props.boards.length === 0) { return (<div className="no-content">Brak board'ów!</div>) } if (this.state.visibilityMap.size === 0) { this.props.boards.map(board => this.state.visibilityMap.set(board.name, true)) } return this.props.boards.map(board => this.renderBoard(board) ); }; renderModal = (board) => { this.setState({ modalShow: true, modalBoard: board, newName: board.name, newBackground: board.background, }) }; handleChangeColor = (color) => { this.setState({ pickedBackground: color }) }; handleCancelColor = () => { this.setState({ showAddBackground: false, showChangeBackground: false, }) }; handleAcceptAddColor = () => { const newColor = this.state.pickedBackground.hex; this.setState({ boardBackground: newColor, showAddBackground: false }) }; handleAcceptChangeColor = () => { const newColor = this.state.pickedBackground.hex; this.setState({ newBackground: newColor, showChangeBackground: false }) }; renderBoard = (board) => { const handleClose = () => { this.setState({ newName: "", newBackground: "", modalShow: false }) }; const switchVisibility = () => { const oldValue = this.state.visibilityMap.get(board.name) this.state.visibilityMap.set(board.name, !oldValue) } const handleEdit = () => { this.props.handleEdit(this.state.modalBoard.name, this.state.newName, this.state.newBackground); handleClose(); this.setState({ modalBoard: "" }); }; return ( <div className="board" style={{backgroundColor: board.background}}> <div className="bookmark board-head" onClick={switchVisibility}> {board.name} <Button className="action-button delete" id={board.name} onClick={this.handleDelete} variant="danger" > X </Button> <Button className="action-button edit" id={board.name} onClick={() => this.renderModal(board)} variant="warning" > O </Button> <Dialog open={this.state.modalShow} aria-labelledby="form-dialog-title"> <DialogTitle id="form-dialog-title">Edytuj boarda {this.state.modalBoard.name}</DialogTitle> <DialogContent> <TextField autoFocus margin="dense" name="newName" label="Nazwa boarda" type="text" onChange={this.handleChange} value={this.state.newName} fullWidth /> <div style={{display: "flex", flexFlow: "nowrap row"}}> <Button variant="light" onClick={() => this.setState({ showChangeBackground: true, pickedBackground: this.state.newBackground })} > Kolor: </Button> <div className="color-box" style={{background: this.state.newBackground}}> </div> <Dialog open={this.state.showChangeBackground} aria-labelledby="form-dialog-title"> <DialogTitle id="form-dialog-title">Kolor boarda {board.name}</DialogTitle> <DialogContent> <PhotoshopPicker header="Wybierz kolor" onAccept={this.handleAcceptChangeColor} onCancel={this.handleCancelColor} color={this.state.pickedBackground} onChangeComplete={this.handleChangeColor}/> </DialogContent> </Dialog> </div> </DialogContent> <DialogActions> <Button onClick={handleClose} color="primary"> Anuluj </Button> <Button onClick={handleEdit} disabled={this.state.newName === "" || !this.state.validate} color="primary"> Zapisz </Button> </DialogActions> </Dialog> </div> <Board isHidden={this.state.visibilityMap.get(board.name)} boardReference={board.ref} name={board.name}/> </div> ) }; renderAddModal = () => { this.setState({ modalAddShow: true, }) }; renderAddBoard = () => { const handleClose = () => { this.setState({ modalAddShow: false, newName: "" }) }; const handleAdd = () => { this.props.handleSubmit(this.state.boardName, this.state.boardBackground); this.setState({boardName: "", boardBackground: "orange"}); handleClose(); this.setState({ modalBoard: "" }); }; return ( <div> <Button className="add-button new-board" onClick={this.renderAddModal} variant="success" > + </Button> <Dialog open={this.state.modalAddShow} aria-labelledby="form-dialog-title"> <DialogTitle id="form-dialog-title">Dodaj board'a</DialogTitle> <DialogContent> <TextField autoFocus margin="dense" name="boardName" label="Nazwa" type="text" onChange={this.handleChange} value={this.state.boardName} fullWidth > </TextField> <div style={{display: "flex", flexFlow: "nowrap row"}}> <Button margin="dense" fullWidth variant="light" onClick={() => this.setState({ showAddBackground: true })} > Kolor: </Button> <div className="color-box" style={{background: this.state.boardBackground}}> </div> </div> <Dialog open={this.state.showAddBackground} aria-labelledby="form-dialog-title"> <DialogTitle id="form-dialog-title">Kolor nowego boarda</DialogTitle> <DialogContent> <PhotoshopPicker header="Wybierz kolor" onAccept={this.handleAcceptAddColor} onCancel={this.handleCancelColor} color={this.state.pickedBackground} onChangeComplete={this.handleChangeColor}/> </DialogContent> </Dialog> </DialogContent> <DialogActions> <Button onClick={handleClose} color="primary"> Anuluj </Button> <Button onClick={handleAdd} disabled={this.state.boardName === "" || !this.state.validate} color="primary"> Dodaj </Button> </DialogActions> </Dialog> </div> ); }; handleDelete = e => { e.preventDefault(); this.props.handleDelete(e.target.id); }; handleChange = e => { e.preventDefault(); const isValid = this.validator(e.target) this.setState({ [e.target.name]: e.target.value, validate: isValid }); }; validator = input => { if (input.name === "newName" && this.state.modalBoard.name === input.value) return true const filter = this.props.boards.find(board => board.name === input.value ) return typeof (filter) === "undefined" } componentDidMount() { setTimeout(function () { this.setState({render: true}) }.bind(this), 1000) } render() { let renderContainer = false; if (this.state.render) { renderContainer = <div className="project-body"> {this.renderBoards()} {this.renderAddBoard()} </div> } return ( renderContainer ) } } export default ProjectView;

Board

-仅从道具中获取isHidden并将其传递给BoardView道具]import React from 'react'; import BoardView from '../views/BoardView'; import {ColumnService} from '../../services/ColumnService'; class Board extends React.Component { constructor(props) { super(props) this.boardReference = this.props.boardReference; this.columnService = new ColumnService(); this.state = { columns: [], isHidden: this.props.isHidden } } componentDidMount() { this.setDatabaseListener(); } handleSubmit = (columnName, order) => { this.columnService.addColumn(columnName, order, this.boardReference); } handleEdit = (name, newColumnName, newColumnOrder) => { this.columnService.editColumn(name, newColumnName, newColumnOrder, this.boardReference); } handleDelete = data => { const name = data.id; this.columnService.deleteColumn(name, this.boardReference); } render() { return ( <BoardView isHidden={this.state.isHidden} columns={this.state.columns} handleSubmit={this.handleSubmit} handleEdit={this.handleEdit} handleDelete={this.handleDelete} /> ) } setDatabaseListener() { this.columnService.columnRef(this.boardReference).onSnapshot(data => { const listOfFetchedColumns = []; data.docs.forEach(doc => { const columnReference = doc.ref; const data = doc.data(); data['ref'] = columnReference; listOfFetchedColumns.push(data); console.log('fetched columns', data); }); listOfFetchedColumns.sort((a, b) => (a.order > b.order) ? 1 : -1) this.setState({ columns: listOfFetchedColumns }); }); } } export default Board;

BoardView

-最后最重要的是,在[[render
import React from 'react'; import {Button} from "react-bootstrap"; import TextField from '@material-ui/core/TextField'; import Dialog from '@material-ui/core/Dialog'; import DialogActions from '@material-ui/core/DialogActions'; import DialogContent from '@material-ui/core/DialogContent'; import DialogTitle from '@material-ui/core/DialogTitle'; import Column from "../controllers/Column"; require("../../styles/Board.css"); require("../../styles/Column.css"); class BoardView extends React.Component { constructor(props) { super(props); this.state = { render: false, modalShow: false, modalAddShow: false, modalColumn: "", columnName: "", columnOrder: "", newName: "", newOrder: "", validate: true, hideColumns: true, isHidden: this.props.isHidden }; this.handleChange = this.handleChange.bind(this); } renderColumns = () => { if (this.props.columns.length === 0) { return (<div className="no-content">Brak kolumn!</div>) } return this.props.columns.map(column => this.renderColumn(column) ); }; renderModal = (column) => { this.setState({ modalShow: true, modalColumn: column, newName: column.name, newOrder: column.order }) }; renderColumn = (column) => { const handleClose = () => { this.setState({ modalShow: false, newName: "", newOrder: "" }) }; const handleEdit = () => { handleClose(); this.props.handleEdit(this.state.modalColumn.name, this.state.newName, parseInt(this.state.newOrder)); this.setState({ modalColumn: "" }); }; return ( <div className="column"> <div className="bookmark column-head"> {column.name} <Button className="action-button delete" id={column.name} onClick={this.handleDelete} variant="danger" > X </Button> <Button className="action-button edit" id={column.name} onClick={() => this.renderModal(column)} variant="warning" > O </Button> <Dialog open={this.state.modalShow} aria-labelledby="form-dialog-title"> <DialogTitle id="form-dialog-title">Edytuj kolumnę {this.state.modalColumn.name}</DialogTitle> <DialogContent> <TextField autoFocus margin="dense" name="newName" label="Nazwa kolumny" type="text" onChange={this.handleChange} value={this.state.newName} fullWidth /> <TextField autoFocus margin="dense" name="newOrder" label="Kolejność kolumny" type="number" min={1} onChange={this.handleChange} value={this.state.newOrder} fullWidth /> </DialogContent> <DialogActions> <Button onClick={handleClose} color="primary"> Anuluj </Button> <Button onClick={handleEdit} disabled={ this.state.newName === "" || this.state.newOrder === "" || this.state.newOrder < 0 || !this.state.validate } color="primary"> Zapisz </Button> </DialogActions> </Dialog> </div> <Column columnReference={column.ref} name={column.name}/> </div> ) }; renderAddModal = () => { this.setState({ modalAddShow: true, }) }; renderAddColumn = () => { const handleClose = () => { this.setState({ modalAddShow: false, newName: "" }) }; const handleAdd = () => { this.props.handleSubmit(this.state.columnName, parseInt(this.state.columnOrder)); this.setState({columnName: "", columnOrder: ""}); handleClose(); this.setState({ modalColumn: "" }); }; return ( <div className="new-column-button-wrapper"> <Button className="add-button new-column" onClick={this.renderAddModal} variant="success" > + </Button> <Dialog open={this.state.modalAddShow} aria-labelledby="form-dialog-title"> <DialogTitle id="form-dialog-title">Dodaj kolumnę</DialogTitle> <DialogContent> <TextField autoFocus margin="dense" name="columnName" label="Nazwa kolumny" type="text" onChange={this.handleChange} value={this.state.columnName} fullWidth > </TextField> <TextField margin="dense" name="columnOrder" label="Kolejność" type="number" min={1} onChange={this.handleChange} value={this.state.columnOrder} fullWidth > </TextField> </DialogContent> <DialogActions> <Button onClick={handleClose} color="primary"> Anuluj </Button> <Button onClick={handleAdd} disabled={ this.state.columnName === "" || this.state.columnOrder === "" || this.state.columnOrder < 0 || !this.state.validate } color="primary"> Dodaj </Button> </DialogActions> </Dialog> </div> ); }; handleDelete = e => { e.preventDefault(); this.props.handleDelete(e.target); }; handleChange = e => { e.preventDefault(); const isValid = this.validator(e.target) this.setState({ [e.target.name]: e.target.value, validate: isValid }); }; validator = input => { if (input.name === "newName" && this.state.modalColumn.name === input.value) return true const filter = this.props.columns.find(column => column.name === input.value ) return typeof (filter) === "undefined" } componentDidMount() { setTimeout(function () { this.setState({render: true}) }.bind(this), 1000) } render() { let renderContainer = false; if (this.state.render) { renderContainer = <div className="board-body" hidden={this.state.isHidden}> {this.renderColumns()} {this.renderAddColumn()} </div> } return ( renderContainer ) } } export default BoardView; Board content is visible - click on board-name to hide it...
Board content is hidden - click on board-name to show it...

感谢您的帮助!

我正在创建与Trello类似的React App。在我们有项目的情况下,项目有电路板,电路板有列,列有任务等。默认情况下只有Project,包含带有木板的条...

javascript reactjs react-native react-props react-state
1个回答
0
投票
© www.soinside.com 2019 - 2024. All rights reserved.