使用 React 生成 Flicking 轮播导致 getComputedStyle 错误
Generating a Flicking carousel with React leads to the getComputedStyle error
这个问题是关于 egjs-flicking 图书馆的,但也许问题更普遍。
让我们考虑两个仅在 render()
方法上有所不同的组件示例。首先我提供整个组件。
import React from 'react';
import Flicking, { MoveEvent, FlickingError } from "@egjs/react-flicking";
class Credits extends React.Component {
constructor(props) {
super(props);
this.readtime = 1000;
this.maxElements = 4;
this.actionReady = this.actionReady.bind(this);
this.actionReset = this.actionReset.bind(this);
this.actionMove = this.actionMove.bind(this);
this.processFlicking = this.processFlicking.bind(this);
}
async actionReady(e) {
const status = e.currentTarget.getStatus();
setTimeout(() => {
e.currentTarget.moveTo(status.position.panel + 1);
}, this.readTime);
}
async actionReset(e, delay) {
setTimeout(() => {
e.currentTarget.moveTo(0);
}, delay);
}
async actionMove(e) {
const status = e.currentTarget.getStatus();
setTimeout(() => {
e.currentTarget.moveTo(status.position.panel + 1);
}, this.readTime);
}
async processFlicking(e) {
const status = e.currentTarget.getStatus();
const remaining = status.panels.length - status.position.panel;
if (remaining == this.maxElements) {
this.actionReset(e, this.readtime*this.maxElements);
} else {
this.actionMove(e);
}
}
getMStyle() {
return {
'overflow': 'hidden'
};
}
render() {
// this is where the examples differ
}
}
静态案例
现在第一种情况是Flicking
容器的子容器是预定义的。
render() {
const PanelComponent = this.props.panelComponent;
return (
<Flicking
style={this.getMStyle()}
circular={false}
align={"prev"}
horizontal={false}
onReady={this.actionReady}
onMoveEnd={this.processFlicking}
>
<div>hello</div><div>sup</div><div>how are u</div><div>cze</div><div>konnichiwa</div><div>salam</div><div>namaste</div>
</Flicking>
);
}
它给出了以下呈现的 HTML
<div class="flicking-camera">
<div>hello</div>
<div>sup</div>
<div>how are u</div>
<div>cze</div>
<div>konnichiwa</div>
<div>salam</div>
<div>namaste</div>
</div>
动态案例
这里是动态生成的
render() {
const PanelComponent = this.props.panelComponent;
return (
<Flicking
style={this.getMStyle()}
circular={false}
align={"prev"}
horizontal={false}
onReady={this.actionReady}
onMoveEnd={this.processFlicking}
>
{ this.props.panels.map((data, index) =>
( <PanelComponent key={index} data={data.content} /> )) }
</Flicking>
);
}
给出以下呈现的 HTML(与之前相同)
<div class="flicking-camera">
<div>hello</div>
<div>sup</div>
<div>how are u</div>
<div>cze</div>
<div>konnichiwa</div>
<div>salam</div>
<div>namaste</div>
</div>
它正在使用的 PanelComponent
class EntryElement extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>{ this.props.data }</div>
)
}
}
生成每个面板。
问题
静态案例完美运行,动态案例给出以下错误
Uncaught (in promise) TypeError: Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'.
at getStyle (utils.ts:259:1)
at Panel.__proto.resize (Panel.ts:323:1)
at Renderer.ts:163:1
at Array.forEach (<anonymous>)
at ReactRenderer.__proto.updatePanelSize (Renderer.ts:163:1)
at Flicking.<anonymous> (Flicking.ts:1227:1)
at step (index.ts:1:1)
at Object.next (index.ts:1:1)
at fulfilled (index.ts:1:1)
我真的很困惑为什么因为结果 HTML 是相同的...有什么想法吗?
好的,我真的找到了。感谢this GitHub discussion and here是我的相关评论。
来自 https://naver.github.io/egjs-flicking/docs/quick-start 我检查了部分 Bypassing ref forwarding
并将 useFindDOMNode={true}
添加到我的 Flicking。
这是能够在 Flicking 中动态放置子组件的完整工作源代码
class Credits extends React.Component {
constructor(props) {
super(props);
this.readtime = 1000;
this.maxElements = 4;
this.actionReady = this.actionReady.bind(this);
this.actionReset = this.actionReset.bind(this);
this.actionMove = this.actionMove.bind(this);
this.processFlicking = this.processFlicking.bind(this);
this.createPanel = this.createPanel.bind(this);
}
async actionReady(e) {
const status = e.currentTarget.getStatus();
setTimeout(() => {
e.currentTarget.moveTo(status.position.panel + 1);
}, this.readTime);
}
async actionReset(e, delay) {
setTimeout(() => {
e.currentTarget.moveTo(0);
}, delay);
}
async actionMove(e) {
const status = e.currentTarget.getStatus();
setTimeout(() => {
e.currentTarget.moveTo(status.position.panel + 1);
}, this.readTime);
}
async processFlicking(e) {
const status = e.currentTarget.getStatus();
const remaining = status.panels.length - status.position.panel;
if (remaining == this.maxElements) {
this.actionReset(e, this.readtime*this.maxElements);
} else {
this.actionMove(e);
}
}
getMStyle() {
return {
'overflow': 'hidden'
};
}
createPanel(panel, index) {
const PanelComponent = this.props.panelComponent;
return <PanelComponent data={panel.content} key={index} />;
}
createPanels(panels) {
return panels.map(this.createPanel);
}
render() {
const panels = this.props.panels;
return (
<Flicking
useFindDOMNode={true}
style={this.getMStyle()}
circular={false}
align={"prev"}
horizontal={false}
onReady={this.actionReady}
onMoveEnd={this.processFlicking}
>
{ this.createPanels(panels) }
</Flicking>
);
}
}
这个问题是关于 egjs-flicking 图书馆的,但也许问题更普遍。
让我们考虑两个仅在 render()
方法上有所不同的组件示例。首先我提供整个组件。
import React from 'react';
import Flicking, { MoveEvent, FlickingError } from "@egjs/react-flicking";
class Credits extends React.Component {
constructor(props) {
super(props);
this.readtime = 1000;
this.maxElements = 4;
this.actionReady = this.actionReady.bind(this);
this.actionReset = this.actionReset.bind(this);
this.actionMove = this.actionMove.bind(this);
this.processFlicking = this.processFlicking.bind(this);
}
async actionReady(e) {
const status = e.currentTarget.getStatus();
setTimeout(() => {
e.currentTarget.moveTo(status.position.panel + 1);
}, this.readTime);
}
async actionReset(e, delay) {
setTimeout(() => {
e.currentTarget.moveTo(0);
}, delay);
}
async actionMove(e) {
const status = e.currentTarget.getStatus();
setTimeout(() => {
e.currentTarget.moveTo(status.position.panel + 1);
}, this.readTime);
}
async processFlicking(e) {
const status = e.currentTarget.getStatus();
const remaining = status.panels.length - status.position.panel;
if (remaining == this.maxElements) {
this.actionReset(e, this.readtime*this.maxElements);
} else {
this.actionMove(e);
}
}
getMStyle() {
return {
'overflow': 'hidden'
};
}
render() {
// this is where the examples differ
}
}
静态案例
现在第一种情况是Flicking
容器的子容器是预定义的。
render() {
const PanelComponent = this.props.panelComponent;
return (
<Flicking
style={this.getMStyle()}
circular={false}
align={"prev"}
horizontal={false}
onReady={this.actionReady}
onMoveEnd={this.processFlicking}
>
<div>hello</div><div>sup</div><div>how are u</div><div>cze</div><div>konnichiwa</div><div>salam</div><div>namaste</div>
</Flicking>
);
}
它给出了以下呈现的 HTML
<div class="flicking-camera">
<div>hello</div>
<div>sup</div>
<div>how are u</div>
<div>cze</div>
<div>konnichiwa</div>
<div>salam</div>
<div>namaste</div>
</div>
动态案例
这里是动态生成的
render() {
const PanelComponent = this.props.panelComponent;
return (
<Flicking
style={this.getMStyle()}
circular={false}
align={"prev"}
horizontal={false}
onReady={this.actionReady}
onMoveEnd={this.processFlicking}
>
{ this.props.panels.map((data, index) =>
( <PanelComponent key={index} data={data.content} /> )) }
</Flicking>
);
}
给出以下呈现的 HTML(与之前相同)
<div class="flicking-camera">
<div>hello</div>
<div>sup</div>
<div>how are u</div>
<div>cze</div>
<div>konnichiwa</div>
<div>salam</div>
<div>namaste</div>
</div>
它正在使用的 PanelComponent
class EntryElement extends React.Component {
constructor(props) {
super(props);
}
render() {
return (
<div>{ this.props.data }</div>
)
}
}
生成每个面板。
问题
静态案例完美运行,动态案例给出以下错误
Uncaught (in promise) TypeError: Failed to execute 'getComputedStyle' on 'Window': parameter 1 is not of type 'Element'.
at getStyle (utils.ts:259:1)
at Panel.__proto.resize (Panel.ts:323:1)
at Renderer.ts:163:1
at Array.forEach (<anonymous>)
at ReactRenderer.__proto.updatePanelSize (Renderer.ts:163:1)
at Flicking.<anonymous> (Flicking.ts:1227:1)
at step (index.ts:1:1)
at Object.next (index.ts:1:1)
at fulfilled (index.ts:1:1)
我真的很困惑为什么因为结果 HTML 是相同的...有什么想法吗?
好的,我真的找到了。感谢this GitHub discussion and here是我的相关评论。
来自 https://naver.github.io/egjs-flicking/docs/quick-start 我检查了部分 Bypassing ref forwarding
并将 useFindDOMNode={true}
添加到我的 Flicking。
这是能够在 Flicking 中动态放置子组件的完整工作源代码
class Credits extends React.Component {
constructor(props) {
super(props);
this.readtime = 1000;
this.maxElements = 4;
this.actionReady = this.actionReady.bind(this);
this.actionReset = this.actionReset.bind(this);
this.actionMove = this.actionMove.bind(this);
this.processFlicking = this.processFlicking.bind(this);
this.createPanel = this.createPanel.bind(this);
}
async actionReady(e) {
const status = e.currentTarget.getStatus();
setTimeout(() => {
e.currentTarget.moveTo(status.position.panel + 1);
}, this.readTime);
}
async actionReset(e, delay) {
setTimeout(() => {
e.currentTarget.moveTo(0);
}, delay);
}
async actionMove(e) {
const status = e.currentTarget.getStatus();
setTimeout(() => {
e.currentTarget.moveTo(status.position.panel + 1);
}, this.readTime);
}
async processFlicking(e) {
const status = e.currentTarget.getStatus();
const remaining = status.panels.length - status.position.panel;
if (remaining == this.maxElements) {
this.actionReset(e, this.readtime*this.maxElements);
} else {
this.actionMove(e);
}
}
getMStyle() {
return {
'overflow': 'hidden'
};
}
createPanel(panel, index) {
const PanelComponent = this.props.panelComponent;
return <PanelComponent data={panel.content} key={index} />;
}
createPanels(panels) {
return panels.map(this.createPanel);
}
render() {
const panels = this.props.panels;
return (
<Flicking
useFindDOMNode={true}
style={this.getMStyle()}
circular={false}
align={"prev"}
horizontal={false}
onReady={this.actionReady}
onMoveEnd={this.processFlicking}
>
{ this.createPanels(panels) }
</Flicking>
);
}
}