Composition 掛載位置錯誤
解決「Composition mounted inside another composition」錯誤,說明 Composition 元件的正確使用位置與場景
錯誤訊息
你可能會看到以下兩種形式的錯誤訊息之一:
在 Remotion Studio 中:
<Composition> mounted inside another composition.
在 Remotion Player 中:
'<Composition> was mounted inside the `component` that was passed to the <Player>.'
問題原因
情境一:在 Remotion Studio 中的巢狀 Composition
這個錯誤發生在你將一個 <Composition> 嵌套在另一個 <Composition> 的組件內部。
// 錯誤:在 MyComp 內部使用 <Composition>
const MyComp: React.FC = () => {
return (
<Composition
id="another-comp"
width={1080}
height={1080}
durationInFrames={30}
fps={30}
component={AnotherComp}
/>
);
};
const Index: React.FC = () => {
return (
<Composition
id="my-comp"
width={1080}
height={1080}
durationInFrames={30}
fps={30}
component={MyComp} // MyComp 內部有另一個 <Composition>,這是錯誤的
/>
);
};情境二:在 Remotion Player 中使用 Composition
這個錯誤發生在你傳給 <Player> 的組件中,回傳了一個 <Composition> 元素。
// 錯誤:在傳給 Player 的組件中使用 <Composition>
const MyComp: React.FC = () => {
return (
<Composition
durationInFrames={300}
fps={30}
width={1080}
height={1080}
id="another-component"
component={AnotherComp}
/>
);
};
const Index: React.FC = () => {
return (
<Player
durationInFrames={300}
fps={30}
compositionWidth={1080}
compositionHeight={1080}
component={MyComp} // MyComp 內部有 <Composition>,這是錯誤的
/>
);
};根本概念
<Composition> 元件只能在 registerRoot() 傳入的根組件中使用,用來向 Remotion 登錄可用的合成(composition)清單。
<Composition> 不是一個可以在其他組件中渲染的視覺元件,它僅僅是一個「登錄聲明」。
在 <Player> 的使用情境中,根本不需要 <Composition> 元件,因為 Player 是直接接受組件的。
解決方案
修正 Remotion Studio 中的巢狀 Composition
移除巢狀的 <Composition>,改為直接掛載組件:
// 正確:直接在 MyComp 中使用 AnotherComp
const MyComp: React.FC = () => {
return <AnotherComp />;
};
// 或者,若需要限制時間或位移,使用 <Sequence>
const MyComp: React.FC = () => {
return (
<Sequence from={0} durationInFrames={30}>
<AnotherComp />
</Sequence>
);
};
// Root.tsx:在根組件中正確登錄所有 Composition
export const RemotionRoot: React.FC = () => {
return (
<>
<Composition
id="my-comp"
width={1080}
height={1080}
durationInFrames={90}
fps={30}
component={MyComp}
/>
</>
);
};修正 Remotion Player 中的錯誤
直接將目標組件傳給 <Player>,不要透過包裝組件:
import { Player } from "@remotion/player";
import { AnotherComp } from "./AnotherComp";
// 正確:直接傳入要播放的組件
const Index: React.FC = () => {
return (
<Player
durationInFrames={300}
fps={30}
compositionWidth={1080}
compositionHeight={1080}
component={AnotherComp} // 直接傳入組件,不要傳包含 <Composition> 的組件
/>
);
};<Composition> vs <Sequence> 的選擇
很多開發者誤用 <Composition> 是因為想達到 <Sequence> 的效果。以下是選擇指引:
| 需求 | 正確做法 |
|---|---|
| 登錄一個可渲染的合成 | <Composition>(只能在 Root 組件中) |
| 在特定時間點顯示子組件 | <Sequence from={30}> |
| 限制子組件的顯示時長 | <Sequence durationInFrames={60}> |
| 在另一個組件中使用某個組件 | 直接寫 <MyComponent /> |
正確的專案結構範例
src/
index.ts ← 呼叫 registerRoot()
Root.tsx ← 只包含 <Composition> 的根組件
MyComposition.tsx ← 實際的視覺組件(不包含 <Composition>)
AnotherComp.tsx ← 另一個視覺組件
// Root.tsx(正確)
import { Composition } from "remotion";
import { MyComposition } from "./MyComposition";
import { AnotherComp } from "./AnotherComp";
export const RemotionRoot: React.FC = () => {
return (
<>
<Composition
id="MyComposition"
component={MyComposition}
durationInFrames={150}
fps={30}
width={1920}
height={1080}
/>
<Composition
id="AnotherComp"
component={AnotherComp}
durationInFrames={90}
fps={30}
width={1920}
height={1080}
/>
</>
);
};