[英]When and in what order does React update the DOM?
I'm having trouble undestanding the exact moment that React updates the DOM. 我遇到了React更新DOM的确切时刻。
Note: I'm using styled-components
in the example below. 注意:我在下面的示例中使用styled-components
。
See this example: 看这个例子:
CodeSandbox: https://codesandbox.io/s/elegant-dirac-j6e54 CodeSandbox: https ://codesandbox.io/s/elegant-dirac-j6e54
It shows a transition of the max-height
property of a container. 它显示了容器的max-height
属性的转换。
It workws as intended. 它按预期工作。 I just don't know WHY it works. 我只是不知道为什么它有效。
The code: 代码:
Two lists: 两个清单:
shortList
needs 70px
of height shortList
需要70px
的高度 longList
needs 124px
of height longList
需要124px
的高度 const shortList = ["Item 1", "Item 2", "Item 3"];
const longList = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6"];
I have a styled-component
container named ListContainerDIV
that will handle the transition based on props
. 我有一个名为ListContainerDIV
的styled-component
容器,它将处理基于props
的转换。 The prop name is idealHeight
. 道具名称是idealHeight
。
const ListContainerDIV = styled.div`
overflow: hidden;
max-height: ${props => props.idealHeight + "px"};
transition: max-height ease-out .5s;
`;
App Component 应用组件
function App() {
// STATE TO KEEP LIST AND REF FOR THE CONTAINER DIV ELEMENT
const [list, setList] = useState(shortList);
const containerDiv_Ref = useRef(null);
// FUNCTION TO TOGGLE BETWEEN LISTS FROM BUTTON CLICK
function changeList() {
setList(prevState => {
if (prevState.length === 3) {
return longList;
} else {
return shortList;
}
});
}
// CALCULATING THE IDEALHEIGHT DURING THE RENDER
let idealHeight = null;
if (list.length === 3) {
idealHeight = 70;
} else if (list.length === 6) {
idealHeight = 124;
}
// RETURNING THE LISTCONTAINER WITH THE `idealHeight` PROP
return (
<React.Fragment>
<button onClick={changeList}>Change List</button>
<ListContainerDIV ref={containerDiv_Ref} idealHeight={idealHeight}>
<ListComponent list={list} />
</ListContainerDIV>
</React.Fragment>
);
}
List Component 列表组件
This is a simple component to render the <ul>
and the <li>'s
这是渲染<ul>
和<li>'s
的简单组件
function ListComponent(props) {
const listItems = props.list.map(item => <li key={item}>{item}</li>);
return <ul>{listItems}</ul>;
}
QUESTION 题
How can this transition be working if I'm setting the max-height
of the component even before the list is rendered? 如果我在渲染列表之前设置组件的max-height
,那么这种转换如何工作呢? I mean, idealHeight
is being set during the App render. 我的意思是,在App渲染期间正在设置idealHeight
。 I was thinking that longList
was going to be rendered in a container that already had max-height = 124
? 我以为longList
将在一个已经有max-height = 124
的容器中呈现? And If that happened, we wouldn't be seeing a transition, right? 如果发生这种情况,我们就不会看到过渡,对吗?
What is the order of events that React is running in this situation? React在这种情况下运行的事件顺序是什么?
Apparently it updates the <ul>
and the <li>'s
before it updates the div
from the styled-component
container. 显然它在更新styled-component
容器的div
之前更新<ul>
和<li>'s
。
An inner component's elements will always be update before the outer component's elements? 内部组件的元素将始终在外部组件的元素之前更新?
UPDATE UPDATE
Just found these tweets from Dan Abramov about this subject: 刚刚从Dan Abramov发现了关于这个主题的这些推文:
https://twitter.com/dan_abramov/status/981869076166344704 https://twitter.com/dan_abramov/status/981869076166344704
With regard to calculating the virtual dom, it starts by rendering the parent components, then renders the child components, then their children, and so on. 关于计算虚拟dom,它首先渲染父组件,然后渲染子组件,然后渲染子组件,依此类推。 All of this uses the latest values for state and props, so both App and the various child components know that the list is longer. 所有这些都使用状态和道具的最新值,因此App和各种子组件都知道列表更长。 This virtual dom is just an in-memory description of what you'd like the page to look like. 这个虚拟dom只是一个内存中描述你想要的页面的样子。
Once the virtual dom has been calculated, react compares the previous virtual dom with the new one, and finds what has changed. 一旦计算出虚拟dom,react会将之前的虚拟dom与新的dom进行比较,并找到已更改的内容。 In this case, it finds that there's a new style that needs to be added to the div, and some new li's that need to be inserted to the ul. 在这种情况下,它发现需要将一个新样式添加到div中,并且需要将一些新的li插入到ul中。 The exact order these are applied are an implementation detail, but they're applied synchronously and the browser cannot paint in between, so it might as well be simultaneously. 这些应用的确切顺序是一个实现细节,但它们是同步应用的,浏览器不能在两者之间绘制,因此它可能同时进行。
The argument passed to useState, shortList in this case, is the initial state. 传递给useState的参数,在这种情况下为shortList,是初始状态。 So when ListContainerDIV is rendered the first time, it's based on the list length being 3, so idealHeight = 70 所以当ListContainerDIV第一次渲染时,它基于列表长度为3,所以idealHeight = 70
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.