2026-06-06 | Frontend PHP Conference Hokkaido 2026 - #frontend_phpcon_do
https://s.su8.run/260606-frontend-phpcon-do
createRoot
例:
フォームの一部だけ複雑になってきた
-> これらを React で書きたい
そもそも:
-> React がほしい部分だけを置き換えたい
<div id="checkbox-group"></div> <script type="module" src="/assets/islands.js"></script>
createRoot(document.getElementById("checkbox-group")!).render( React.createElement(CheckboxGroup) );
src/*.tsx
React を動かすだけの話だったはずなのに……
Smarty 側では「ここで CheckboxGroup を mount する」ということだけを書く
<div data-react-island="CheckboxGroup"></div>
const islands = { CheckboxGroup, } satisfies Record<string, ComponentType<unknown>>; document.querySelectorAll("[data-react-island]").forEach((el) => { const name = el.getAttribute("data-react-island"); const props = JSON.parse(el.getAttribute("data-props") ?? "{}"); const Component = islands[name!]; createRoot(el).render(<Component {...props} />); });
Smarty 側で JSON を埋め込む
<div data-react-island="CheckboxGroup" data-props='{$checkboxGroupPropsJson|escape:"html"}' ></div>
attributes に < や " が入るとつらい -> json_encode 後に HTML escape すると安全
<
"
json_encode
manifest は「entry 名」と「build 後のファイル名」の対応表
{ "src/islands.tsx": { "file": "assets/islands-Bi7oDEnV.js", "css": ["assets/islands-lwNXSBIb.css"] } }
-> Smarty は安定した entry 名だけ知っていればよい
テンプレートには entry 名だけを書く
{react_assets entry="src/islands.tsx"}
↓
<link rel="stylesheet" href="/assets/islands-lwNXSBIb.css"> <script type="module" src="/assets/islands-Bi7oDEnV.js"></script>
src/islands.tsx
file
css
link
script