React 渲染道具的意外行为
Unexpected behavior of React render props
我使用 React Transition Group 编写了以下代码:
const Transition = ({ elements, selectKey, render: Element, ...props }) => (
<TransitionGroup {...props}>
{elements.map((element) => (
<CSSTransition
key={selectKey(element)}
timeout={1000}
className="transition-slide"
>
<Element {...element} />
</CSSTransition>
))}
</TransitionGroup>
)
这里的关键部分是 Transition
组件接收 render
道具并应用一些过渡渲染它。
我期望的工作方式:
<Transition render={(props) => <Toast {...props} />} />
但是这段代码并不像我预期的那样工作:下一个元素的转换中断前一个元素的转换。
但是,这段代码工作正常:
const Element = (props) => <Toast {...props} />
// ...
<Transition render={Element} />
如何在不将所需的 render-prop 放入单独的组件中的情况下解决此问题?
Codesandbox:Example sandbox。沙盒提供了一个 non-working 选项,动画中断。要获得工作版本,您需要取消注释 /Toasts/index.js
文件
中的第 16 行和第 30 行
P.S. I can't just use render={Toast}
because I need to do ({id}) => <Toast dismiss={() => {deleteToast(id)}} />
. I omitted this detail in order to simplify the understanding of the problem.
如果您不想将渲染函数放入另一个组件,将其放入 useCallback() 即可解决。
const Toasts = () => {
const [toasts, addToast] = useToasts();
const Element = useCallback((props) => <Toast {...props} />, []);
return (
<div>
<button onClick={addToast}>Add toast</button>
<List>
<Transition
elements={toasts}
selectKey={({ id }) => id}
render={Element}
/>
</List>
</div>
);
}
(我不太明白问题的根源,但它与函数引用有关。)
我使用 React Transition Group 编写了以下代码:
const Transition = ({ elements, selectKey, render: Element, ...props }) => (
<TransitionGroup {...props}>
{elements.map((element) => (
<CSSTransition
key={selectKey(element)}
timeout={1000}
className="transition-slide"
>
<Element {...element} />
</CSSTransition>
))}
</TransitionGroup>
)
这里的关键部分是 Transition
组件接收 render
道具并应用一些过渡渲染它。
我期望的工作方式:
<Transition render={(props) => <Toast {...props} />} />
但是这段代码并不像我预期的那样工作:下一个元素的转换中断前一个元素的转换。
但是,这段代码工作正常:
const Element = (props) => <Toast {...props} />
// ...
<Transition render={Element} />
如何在不将所需的 render-prop 放入单独的组件中的情况下解决此问题?
Codesandbox:Example sandbox。沙盒提供了一个 non-working 选项,动画中断。要获得工作版本,您需要取消注释 /Toasts/index.js
文件
P.S. I can't just use
render={Toast}
because I need to do({id}) => <Toast dismiss={() => {deleteToast(id)}} />
. I omitted this detail in order to simplify the understanding of the problem.
如果您不想将渲染函数放入另一个组件,将其放入 useCallback() 即可解决。
const Toasts = () => {
const [toasts, addToast] = useToasts();
const Element = useCallback((props) => <Toast {...props} />, []);
return (
<div>
<button onClick={addToast}>Add toast</button>
<List>
<Transition
elements={toasts}
selectKey={({ id }) => id}
render={Element}
/>
</List>
</div>
);
}
(我不太明白问题的根源,但它与函数引用有关。)