当我在另一个功能组件中定义React功能组件时,为什么(一些)CSS样式会中断



为什么在另一个功能组件中定义React功能组件会破坏CSS转换?

function Doohick({isOpen}: {isOpen: boolean}) {
const style = {
transition: 'opacity 2s ease',
...(isOpen ? {opacity: 1} : {opacity: 0})
}
return (
<div style={style}>
Doohick!!!
</div>
)
}
function Parent() {
const [open, isOpen] = useState(false)
return (
<>
<button onClick={() => setIsOpen(!isOpen)}>Toggle Doohick</button>
<Doohick isOpen={isOpen} />
</>
)
}

如果我在Parent之外定义Doohick,如上所述,一切都很好。如果我在Parent中移动定义,并且没有其他更改,我的CSS转换就会中断。其他CSS属性也可以。

为什么在另一个功能组件中定义功能组件会破坏CSS转换

我为什么要这么做的复杂解释

我听到你在问:我为什么要这么做?我会告诉你,但请记住,你不需要知道任何这些就可以理解具体的问题。

我想将Doohick状态封装在一个自定义挂钩中:

function useDoohick() {
const [isOpen, setIsOpen] = useState(false)

const ToggleButton = 
<Button onClick={() => setIsOpen(!isOpen)}>Toggle Doohick</Button>

const Doohick = <MyDoohick show={isOpen}/>
return {ToggleButton, Doohick} 
}
function Parent() {
const {Doohick, ToggleButton} = useDoohick()
return (
<>
{ToggleButton}
{Doohick}
</>
)
}

但我也希望Parent能够将自己的道具传递到DoohickToggleButton中。我可以几乎这样实现:

function useDoohick() {
const [isOpen, setIsOpen] = useState(false)

const ToggleButton = ({text}) =>
<Button 
onClick={() => setIsOpen(!isOpen)}
>
{text}
</Button>

const Doohick = () => 
<MyDoohick show={isOpen} />
return {ToggleButton, Doohick} 
}
function Parent() {
return (
<>
<ToggleButton text='Burninate' />
<Doohick />
</>
)
}

这就像广告中所说的那样:ToggleButton使用期望的标签进行渲染,并控制是否显示Doohick。但是这个模式打破了我在Doohick上定义的一些CSS样式(特别是转换(。其他款式也可以。

我仍然可以这样称呼它:

function Parent() {
return (
<>
{ToggleButton({text: 'Burninate'})}
{Doohick()}
</>
)
}

并且过渡正常工作。但我更喜欢这里的标准JSX语法:

<ToggleButton text='Burninate />

显然,<Doohick />Doohick()是不同的。但是,前者是什么打破了CSS的转换呢?

问题的根源可以归结为在Parent中定义自定义组件。钩子本身是无关紧要的。但是这种在自定义钩子中封装状态同时返回可自定义组件的模式非常强大,几乎都能工作,所以我希望有一种方法可以保存它。

TL;DR

为什么在另一个组件中定义一个组件会破坏我的CSS转换(可能还有我还没有找到的其他样式(?在仍然使用JSX风格的语法调用嵌套组件的情况下,如何绕过这一问题?

在另一个组件中定义一个组件总是会导致这样的问题。每次渲染外部零部件时,都会创建内部零部件的全新定义。它可能与上一次渲染中的文本相同,但它在内存中是不同的函数,因此只要react可以判断它是不同类型的组件。

在协调更改时,组件类型是react查找的主要内容。由于类型发生了更改,react被迫卸载旧组件,然后装载新组件。因此,与其在页面上有一个样式正在更改的<div>,不如有一个带有某种样式的div,然后它被删除,一个不相关的div被放到页面上。它可能有不同的风格,但由于这是一个全新的div,transition属性不会起任何作用。

最新更新