[英]React does not update style on rerender
我有一個 React 組件,用戶可以更改其可見性和位置。
通過添加和刪除 CSS 類的可見性,通過函數的位置,將拖放后的新位置設置為頂部和左側。
這行得通,但我的問題是 React 不會更新樣式(因此不會將位置重寫為初始位置),當組件被重新渲染以獲得可見性時。
class MoveableCard extends React.Component {
...
render() {
...
return <div className={(this.props.isVisible ? '' : 'hide')}
draggable="true" onDragStart={dragStart}
style={{top:'initial', left:'initial'}}>
...
</div>
}
}
function dragStart(event) {
var style = window.getComputedStyle(event.target, null)
event.dataTransfer.setData("text/plain", JSON.stringify({
id:event.target.getAttribute('data-reactid'),
x:(parseInt(style.getPropertyValue("left"),10) - event.clientX),
y:(parseInt(style.getPropertyValue("top"),10) - event.clientY)
}))
}
function dragOver(event) {
event.preventDefault()
return false
}
function drop(event) {
let data = JSON.parse(event.dataTransfer.getData("text/plain"))
let el = document.querySelectorAll("[data-reactid='" + data.id + "']")[0]
el.style.left = (event.clientX + parseInt(data.x, 10)) + 'px'
el.style.top = (event.clientY + parseInt(data.y, 10)) + 'px'
event.preventDefault()
return false
}
document.body.addEventListener('dragover',dragOver,false)
document.body.addEventListener('drop',drop,false)
第一次渲染卡片時,樣式看起來像style="top: initial; left: initial;"
.
當卡片被移動時,樣式看起來像style="top: 162px; left: 320px;"
.
當卡片關閉時,類hide
被添加,但樣式保持style="top: 162px; left: 320px;"
,不管我如何創建樣式對象。
那么,我怎樣才能強制 React 更新樣式呢? 還是有另一種方法可以做到這一點?
答案的簡短版本:
使用內部狀態和組件生命周期
長版:
首先,我建議將您的事件處理程序放在組件中而不是全局方法中:
class MoveableCard extends React.Component {
dragStart(event) {}
dragOver(event) {}
drop(event) {}
}
其次,在組件的構造函數中,將組件的 this-context 綁定到這些處理程序。 (好吧,或者你在渲染方法中使用箭頭函數)
constructor() {
this.dragStart = this.dragStart.bind(this);
this.dragOver = this.dragOver.bind(this);
this.drop = this.drop.bind(this);
}
為了讓組件“更新”或重新渲染,我建議在這種情況下改變其內部狀態。 因此,您首先在componentWillMount 內的初始狀態中添加一個初始值。
componentWillMount() {
this.state = { top: 0, left: 0 };
}
在事件處理程序中,您現在可以使用 this.setState 更新 innerState 的 top 和 left(這就是您綁定 this 所需要的)。
drop() {
// Assuming you filled in this.left and this.top in the dragOver method
this.setState({ top: this.top, left: this.left });
}
通過使用 setState,將使用內部狀態的新值觸發重新渲染。 現在,您可以在您的渲染方法中使用this.state.top
和this.state.left
:
render() {
return (
<div className={(this.props.isVisible ? '' : 'hide')}
draggable="true"
onDragStart={this.dragStart}
style={{top: this.state.top, left: this.state.left}}>
</div>
);
}
好的,根據 Andrew、dejakob 和 Chris 的回答得到了解決方案,謝謝大家 :)
我最初認為,我無法將函數移動到組件中,因為具有最終位置的放置事件是由我放置卡片的元素發出的,而不是卡片本身。
但是有一個dragend
事件,它由 Card 發出並包含位置。
現在我只需要使用它來設置狀態中的位置(並通過 ref 將其刪除到父級中的unsetPosition
)。
class MoveableCard extends React.Component {
constructor(props) {
super(props)
this.state = {
styles: {top:'initial', left:'initial'}
}
this.drop = this.drop.bind(this);
}
dragStart(e) {
let style = window.getComputedStyle(e.target, null)
this.setState({l: parseInt(style.getPropertyValue("left")) - e.clientX, y: parseInt(style.getPropertyValue("top")) - e.clientY})
}
drop(e) {
this.setState({left: this.state.l + e.clientX, top: this.state.y + e.clientY})
e.preventDefault()
return false
}
unsetPosition() {
this.setState({styles: {top:'initial', left:'initial'}})
}
render() {
return <div className={(this.props.isVisible ? '' : 'hide')}
draggable="true"
onDragStart={this.dragStart}
onDragEnd={this.drop}
style={this.state.styles}>
...
</div>
}
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.