{"id":15529001,"url":"https://github.com/alexander-schranz/twig-for-react-devs","last_synced_at":"2025-04-23T12:34:52.075Z","repository":{"id":88923519,"uuid":"337162384","full_name":"alexander-schranz/twig-for-react-devs","owner":"alexander-schranz","description":"Twig for react devs. A guide to get react developers faster into the twig template engine.","archived":false,"fork":false,"pushed_at":"2021-02-10T10:47:43.000Z","size":56,"stargazers_count":22,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-03-29T23:41:17.583Z","etag":null,"topics":["alexander-schranz-article","reactjs","symfony","twig"],"latest_commit_sha":null,"homepage":"","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alexander-schranz.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-02-08T17:56:54.000Z","updated_at":"2024-09-04T22:18:33.000Z","dependencies_parsed_at":"2023-06-13T04:15:41.158Z","dependency_job_id":null,"html_url":"https://github.com/alexander-schranz/twig-for-react-devs","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexander-schranz%2Ftwig-for-react-devs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexander-schranz%2Ftwig-for-react-devs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexander-schranz%2Ftwig-for-react-devs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alexander-schranz%2Ftwig-for-react-devs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alexander-schranz","download_url":"https://codeload.github.com/alexander-schranz/twig-for-react-devs/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250435844,"owners_count":21430365,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["alexander-schranz-article","reactjs","symfony","twig"],"created_at":"2024-10-02T11:15:51.642Z","updated_at":"2025-04-23T12:34:52.031Z","avatar_url":"https://github.com/alexander-schranz.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# Twig for react devs\n\nAn easy guide for react developers getting into PHP Twig template engine from Symfony.\n\n![Header](images/logos/social.png)\n\n## Introduction\n\nHello 👋,\n\nMy name is Alexander Schranz ([alex_s_](https://twitter.com/alex_s_)) and I'm fulltime Webdeveloper\nworking on the [SULU CMS](https://sulu.io/?utm_source=github\u0026utm_medium=repository\u0026utm_campaign=alex-twig-for-react-devs)\nand did based on that created a lot of websites.\n\nWith this article I wanted to make it easier for React Developers\ngetting into the Twig Syntax.\n\nEvery Section will first Provide the `React JS` ⚛️ code and then the `Twig` 🌱\nfollowed by explanation about the difference between them.\n\nAt the start I want to mention here that `Twig` was inspired a lot by\n[Jinja2 Template Engine](https://github.com/pallets/jinja)\ndeveloped for the Django Python Framework, but was improved\nover the years with other new features by the Symfony Team.\n\nBefore continue with the overview the best comparison is\nwhat `JSX` is for `React` (JS), `Twig` is for `Symfony` (PHP).\nSo all Business Logic should live outside of it.\n\n**Table of Contents**\n\n - [Outputting a variable](#outputting-a-variable)\n - [Outputting raw HTML](#outputting-raw-html)\n - [If statements](#if-statements)\n - [Loops](#loops)\n - [Base Template](#base-template)\n - [Providing props to templates](#providing-props-to-templates)\n - [Include and override parts](#include-and-override-parts)\n - [Dynamic Include](#dynamic-include)\n - [Conclusion](#conclusion)\n\n## Outputting a variable\n\nIn the first example we will to the most simpliest thing just\noutputting a variable we did create in our component / template.\n\n### Outputting a variable (React JS ⚛️)\n\n```js\n// src/views/My.js\n\nimport React from 'react';\n\nclass My extends React.Component {\n    render() {\n        const title = 'My Title';\n        \n        return \u003ch1\u003e{title}\u003c/h1\u003e;\n    }\n}\n```\n\n### Outputting a variable (Twig 🌱)\n\n```twig\n{# templates/pages/my.html.twig #}\n\n{% set title = 'My Title' %}\n\n\u003ch1\u003e{{ title }}\u003c/h1\u003e\n```\n\n### Outputting a variable (Explanation)\n\nOutputting a variable in Twig and JSX is very similar instead\nof `{variable}` you use `{{ variable }}`. The spaces are optional\nbut recommended by  the [Twig coding standards](https://twig.symfony.com/doc/3.x/coding_standards.html).\n\n## Outputting raw HTML\n\nThere are cases where you use CKEditor or other rich text editors \nto create content which will provide you raw HTML code you would\nlike to render in this case you want not that your variable you\nwant to outputted does get escaped.\n\n### Outputting raw HTML (React JS ⚛️)\n\n```js\n// src/views/My.js\n\nimport React from 'react';\n\nclass My extends React.Component {\n    render() {\n        const someHtml = '\u003cp\u003eMy Text editor content\u003c/p\u003e';\n\n        return \u003cdiv dangerouslySetInnerHTML={{_html: someHtml}} /\u003e;\n    }\n}\n```\n\n### Outputting raw HTML (Twig 🌱)\n\n```twig\n{# templates/pages/my.html.twig #}\n\n{% set someHtml = '\u003cp\u003eMy Text editor content\u003c/p\u003e' %}\n\n\u003cdiv\u003e\n    {{ someHtml|raw }}\n\u003c/div\u003e\n```\n\n### Outputting raw HTML (Explanation)\n\nBoth (`React JS` and `Twig`) escape variables by default so no HTML\ninjected without  a call of an additional prop or filter.\n\nThere are in Twig other ways to disable `autoescape` over a whole\ncontent. See for this the [official Twig Docs](https://twig.symfony.com/doc/3.x/api.html#escaper-extension).\n\nI personally recommend only using the `|raw` filter todo this kind\nof things.\n\n## If statements\n\n### If statements (React JS ⚛️)\n\n```js\n// src/views/My.js\n\nimport React from 'react';\n\nclass My extends React.Component {\n    render() {\n        var title = 'Test' ;\n        const list = ['Test', 'Test 2'];\n\n        // Basic equal if statement\n        if (title == 'test') {\n            title = 'Basic equal if statement';\n        // Not equal if statement\n        } else if (title != 'test') {\n            title = 'Not equal if statement';\n        // Typesafe if statemenet\n        } else if (title === false) {\n            title = 'Typesafe if statemenet';\n        // Typesafe not if statemenet\n        } else if (title !== false) {\n            title = 'Typesafe not if statemenet';\n        // In array if statemenet\n        } else if (list.includes(title)) {\n            title = 'In array if statemenet';\n        // Not in array if statemenet\n        } else if (!list.includes(title)) {\n            title = 'Not in array if statemenet';\n        // Greater if statement\n        } else if (title \u003e 10) {\n            title = 'Greater if statement';\n        // And if statement\n        } else if (title \u003e 10 \u0026\u0026 title \u003c 10) {\n            title = 'And if statement';\n        // Or if statement\n        } else if (title \u003e 10 || title != 0) {\n            title = 'Or if statement';\n        // Else if statement\n        } else {\n            title = 'Else if statement';\n        }\n        \n        return \u003cdiv\u003e\n            {title}\n            \n            {title ? title : 'Other'}\n        \u003c/div\u003e;\n    }\n}\n```\n\n### If statements (Twig 🌱)\n\n```twig\n{# templates/pages/my.html.twig #}\n\n{% set title = 'Test' %}\n{% set list = ['Test', 'Test 2'] %}\n\n{# Basic equal if statement #}\n{% if title == 'test' %}\n    {% set title = 'Basic equal if statement' %}\n{# Basic not equal if statement #}\n{% elseif title != 'test' %}\n    {% set title = 'Basic not equal if statement' %}\n{# Typesafe if statement #}\n{% elseif title same as(false) %} {# Very uncommon in Twig todo typesafe checks #}\n    {% set title = 'Typesafe if statement' %}\n{# Typesafe not if statement #}\n{% elseif title not same as(false) %} {# Very uncommon in Twig todo typesafe checks #}\n    {% set title = 'Typesafe not if statement' %}\n{# In array if statement #}\n{% elseif title in list %}\n    {% set title = 'In array if statement' %}\n{# Not in array if statement #}\n{% elseif title not in list %}\n    {% set title = 'Not in array if statement' %}\n{# Greater if statement #}\n{% elseif title \u003e 10 %}\n    {% set title = 'Greater if statement' %}\n{# And if statement #}\n{% elseif title \u003e 10 and title \u003c 10 %}\n    {% set title = 'And if statement' %}\n{# Or if statement #}\n{% elseif title \u003e 10 or title != 0 %}\n    {% set title = 'Or if statement' %}\n{# Else if statement #}\n{% else %}\n    {% set title = 'Else if statement' %}\n{% endif %}\n\n\u003cdiv\u003e\n    {{ title }}\n    \n    {{ title ?: 'Other' }}\n\u003c/div\u003e\n```\n\n### If statements (Explanation)\n\nFor if statement the [if tag](https://twig.symfony.com/doc/3.x/tags/if.html)\nis used. Where in JavaScript it is very common to have\ntypesafe check with `===`. This is very uncommon in twig\nbecause Twig is really focused being a template engine and\nnot a language where you should build business logic.\n\nIt is still possible in Twig doing a typesafe check using \nthe [same as test](https://twig.symfony.com/doc/3.x/tests/sameas.html).\n\nTwig like PHP supports also the ternary operator (`?:`) and the\nnull-coalescing operator (`??`). Read more about them in the\n[Twig operators documentation](https://twig.symfony.com/doc/3.x/templates.html#other-operators).\n\n## Loops\n\n### Loops (React JS ⚛️)\n\n```js\n// src/views/My.js\n\nimport React from 'react';\n\nclass My extends React.Component {\n    render() {\n        const list = [{\n            title: 'List Item 1',\n        }, {\n            title: 'List Item 2',\n        }];\n        \n        return \u003cul\u003e\n            {list.map((item) =\u003e {\n                return \u003cli\u003e\n                    {item.title}\n                \u003c/li\u003e;\n            })}\n        \u003c/ul\u003e;\n    }\n}\n```\n\n### Loops (Twig 🌱)\n\n```twig\n{# templates/pages/my.html.twig #}\n\n{% set list = [\n    {\n        title: 'List Item 1',\n    },\n    {\n        title: 'List Item 2',\n    }\n] %}\n\n\u003cul\u003e\n    {% for item in list %}\n        \u003cli\u003e{{ item.title }}\u003c/li\u003e\n    {% endfor %}\n\u003c/ul\u003e\n```\n\n### Loops (Explanation)\n\nWhere in `JavaScript` different way of looping exist in twig\nyou will work with the [for](https://twig.symfony.com/doc/3.x/tags/for.html)\nto loop over variables.\n\nTwig here supports some range function to make developing of\ntemplates easier for example:\n\n```twig\n{# Output numbers from 0 - 10 #}\n{% for i in 0..10 %}\n    * {{ i }}\n{% endfor %}\n\n{# Output letters from a-z #}\n{% for i in 'a'..'z' %}\n    * {{ i }}\n{% endfor %}\n\n{# Output letters from A-Z #}\n{% for letter in 'a'|upper..'z'|upper %}\n    * {{ letter }}\n{% endfor %}\n```\n\nBy default inside the `for` loop Twig provide some magic variable\ncalled `loop` which will provide you the following data:\n\n```twig\n{% for i in 0..10 %}\n    {{ loop.index }} {# index beginning with 1 #}\n    {{ loop.index0 }} {# index beginning with 0 #}\n    {{ loop.revindex }} {# reverted index #}\n    {{ loop.revindex0 }} {# reverted index0 #}\n    {{ loop.first }} {# boolean flag if its the first item of this loop #}\n    {{ loop.last }} {# boolean flag if its the last item of this loop #}\n    {{ loop.length }} {# the number of items of this loop #}\n    {{ loop.parent }} {# access the parent loop variable if using nested loops #}\n{% endfor %}\n```\n\nWhere in `React JS` you maybe need a `counter` or accessing the length\nin `Twig` the `loop` variable is available inside every loop and make\nit easy to add CSS classes to first or last items of a loop.\n\nSee here also the Twig documentation about the [for](https://twig.symfony.com/doc/3.x/tags/for.html)\ntag.\n\nAs `React JS` has access to all `JavaScript` array available function\nTwig also has it tricks to make outputting of html very simple.\n\nSo for example let see that we have variable which content is the\nfollowing:\n\n```js\n[\"1\", \"2\", \"3\", \"4\", \"5\"]\n```\n\nand we want to render the following HTML:\n\n```html\n\u003cdiv\u003e\n    \u003cdiv class=\"row\"\u003e\n        \u003cdiv class=\"col-4\"\u003e\n            1\n        \u003c/div\u003e\n\n        \u003cdiv class=\"col-4\"\u003e\n            2\n        \u003c/div\u003e\n\n        \u003cdiv class=\"col-4\"\u003e\n            3\n        \u003c/div\u003e\n    \u003c/div\u003e\n    \n    \u003cdiv class=\"row\"\u003e\n        \u003cdiv class=\"col-4\"\u003e\n            4\n        \u003c/div\u003e\n\n        \u003cdiv class=\"col-4\"\u003e\n            5\n        \u003c/div\u003e\n\n        \u003cdiv class=\"col-4\"\u003e\n            \n        \u003c/div\u003e\n    \u003c/div\u003e\n\u003c/div\u003e\n```\n\nThis can in Twig easily be rendered by the `batch` function\nthe following way:\n\n```twig\n\u003cdiv\u003e\n    {% for row in list|batch(3, '') %}\n        \u003cdiv class=\"row\"\u003e\n            {% for item in row %}\n                \u003cdiv class=\"col-4\"\u003e\n                    {{ item }}\n                \u003c/div\u003e\n            {% endfor %}\n        \u003c/div\u003e\n    {% endfor %}\n\u003c/div\u003e\n```\n\nRead here also the offical documentation about the\n[Twig batch function](https://twig.symfony.com/doc/3.x/filters/batch.html).\n\n## Base Template\n\nThe first you mostly create when building a website is a base\ntemplate or base component which contains all things which your\ntemplates have in common like Navigation, Footer, Header.\n\n### Base Template (React JS ⚛️)\n\nIn react for rendering anything we first need to create a\n`index.html` where the react application is started which also\ncontains the minimal required html for a page.\n\n```html\n\u003c!-- src/index.html ---\u003e\n\u003c!doctype html\u003e\n\u003chtml lang=\"en\"\u003e\n\u003chead\u003e\n\n\u003c/head\u003e\n\u003cbody id=\"app\"\u003e\n    \u003cscript src=\"app.js\"\u003e\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nIn react a base template could look like the following.\n\n```js\n// src/views/Base.js\n\nimport React from 'react';\nimport Head from 'next/head'\nimport Navigation from './components/Navigation';\nimport Header from './components/Header';\nimport Footer from './components/Footer';\n\nclass Base extends React.Component {\n    render() {\n        const {\n            header\n        } = this.props;\n        \n        const headerComponent = header ? header : \u003cHeader /\u003e;\n        \n        return \u003cdiv\u003e\n            \u003cHead\u003e\n                \u003ctitle\u003e{this.props.title}\u003c/title\u003e\n                \u003cmeta name=\"viewport\" content=\"initial-scale=1.0, width=device-width\" /\u003e\n            \u003c/Head\u003e\n            \n            \u003cNavigation /\u003e\n            \n            \u003cHeader /\u003e\n            \n            \u003cdiv className=\"content\"\u003e\n                {this.props.children}\n            \u003c/div\u003e\n\n            \u003cFooter /\u003e\n        \u003c/div\u003e;\n    }\n}\n```\n\nA default template build on top of the base template will look like the following way:\n\n```js\n// src/views/Default.js\n\nimport React from 'react';\nimport Base from './components/Base';\n\nclass Default extends React.Component {\n    render() {\n        const title = 'Some Title';\n\n        return \u003cBase title={title}\u003e\n            \u003ch1\u003e{title}\u003c/h1\u003e\n        \u003c/Base\u003e;\n    }\n}\n```\n\nA homepage template build on top of the base template could look this way\nwhich will override the Header component:\n\n```js\n// src/views/Homepage.js\n\nimport React from 'react';\nimport Base from './components/Base';\nimport HeaderBig from './components/HeaderBig';\n\nclass Homepage extends React.Component {\n    render() {\n        const title = 'Some Title';\n\n        return \u003cBase title={title}\n                     header={\u003cHeaderBig /\u003e}\u003e\n            \u003ch1\u003e{title}\u003c/h1\u003e\n        \u003c/Base\u003e;\n    }\n}\n```\n\nThis way we created a reusable base which can be used in all components again.\n\n### Base Template (Twig 🌱)\n\nTo implement the same as we did above we need to create the following\nin our Twig structure. As Twig is server rendered by PHP in Symfony\nwe will create the `base.html.twig` which will contain the html which\nwas in react rendered by `index.html` and `Base.js`.\n\n```twig\n{# templates/base.html.twig #}\n\u003c!doctype html\u003e\n\u003chead lang=\"en\"\u003e\n    \u003ctitle\u003e{title}\u003c/title\u003e\n    \u003cmeta name=\"viewport\" content=\"initial-scale=1.0, width=device-width\" /\u003e\n\u003c/head\u003e\n\u003cbody\u003e\n    {% include 'include/navigation.html.twig' %}\n    \n    {% block header %}\n        {% include 'include/header.html.twig' %}\n    {% endblock %}\n    \n    {% block content %}{% endblock %}\n    \n    {% include 'include/footer.html.twig' %}\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nAnd now we create the 2 templates file which use this `base.html.twig` file.\n\n```twig\n{# templates/pages/default.html.twig #}\n{% extends 'base.html.twig' %}\n\n{% block content %}\n    \u003ch1\u003e{title}\u003c/h1\u003e\n{% endblock %}\n```\n\nWe will also create the `homepage.html.twig` with a custom header.\n\n```twig\n{# templates/pages/homepage.html.twig #}\n{% extends 'base.html.twig' %}\n\n{% block header %}\n    {% include 'include/header-big.html.twig' %}\n{% endblock %}\n\n{% block content %}\n    \u003ch1\u003e{title}\u003c/h1\u003e\n{% endblock %}\n```\n\n### Base Template (Explanation)\n\nAs you see in this example the `extends` will say from which template\nthey should inherit and with the `block` feature of Twig we can then\nprovide content or override the defined `blocks` like `header` and\n`content` in our Twig template.\n\nInstead of importing a components like its done react we will use\nin Twig the `include` block/method of Twig to render the content of another twig\ntemplate.\n\nHas in this case a look at the [extends tag documentation](https://twig.symfony.com/doc/3.x/tags/extends.html)\nand [include tag documentation](https://twig.symfony.com/doc/3.x/tags/include.html)\nfrom the official [Twig Documentation](https://twig.symfony.com/).\n\n## Providing props to templates\n\n### Providing props to templates (React JS ⚛️)\n\n```js\n// src/views/Parent.js\n\nimport React from 'react';\nimport Child from './components/Child';\n\nclass Parent extends React.Component {\n    render() {\n        const someTitle = 'Some Title';\n\n        return \u003cChild title={someTitle} /\u003e;\n    }\n}\n```\n\n### Providing props to templates (Twig 🌱)\n\n```twig\n{% set title = 'Some Title' %}\n\n{% include 'includes/child.html.twig' %}\n```\n\n### Providing props to templates (Explanation)\n\nWhere in `React JS` the only way to give properties from a parent\nto a child is giving them as a `props` in `Twig` by default a\nincluded `Template` has access to all variables which were defined\nor are accessible in the parent template.\n\nTwig still provide ways to provide properties to included template\nthis way:\n\n```twig\n{% include 'includes/child.html.twig' with { title: 'Some Title' } %}\n```\n\nIf you don't want that the included template can access the variables\ndefined in the parent template this can be avoided using the `only`\nkeyword:\n\n```twig\n{% set someTitle = 'Some Title' %}\n\n{% include 'includes/child.html.twig' with { title: someTitle } only %}\n```\n\nRead more about the include tag in the official [Twig Include Documentation](https://twig.symfony.com/doc/3.x/tags/include.html).\n\n## Include and override parts\n\nSometimes you need to include and override a specific template\nor Component. In this section we will look at this parts.\n\n### Include and override parts (React JS ⚛️)\n\n```js\n// src/views/Parent.js\n\nimport React from 'react';\nimport Child from './components/Child';\nimport CustomHeader from './components/CustomHeader';\nimport CustomFooter from './components/CustomFooter';\n\nclass Parent extends React.Component {\n    render() {\n        return \u003cChild\n                header={\u003cCustomHeader /\u003e}\n                footer={\u003cCustomFooter /\u003e}\u003e\n            {this.props.children}\n        \u003c/Child\u003e;\n    }\n}\n```\n\n```js\n// src/component/Child.js\n\nimport React from 'react';\nimport Child from './components/Child';\nimport Header from './components/Header';\nimport Footer from './components/Footer';\n\nclass Parent extends React.Component {\n    render() {\n        const HeaderComponent = this.props.header ? this.props.header : \u003cHeader /\u003e;\n        const FooterComponent = this.props.footer ? this.props.footer : \u003cFooter /\u003e;\n        \n        return \u003cdiv\u003e\n            {HeaderComponent}\n            {FooterComponent}\n        \u003c/div\u003e;\n    }\n}\n```\n\n### Include and override parts (Twig 🌱) (using include)\n\n```twig\n{# templates/pages/parent.html.twig #}\n\n{% include 'includes/other-child.html.twig' %}\n```\n\n```twig\n{# templates/pages/other-child.html.twig #}\n\n{% extends 'includes/child.html.twig' %}\n\n{% block header %}\n    {% include 'includes/custom-header.html.twig' %}\n{% endblock %}\n\n{% block content %}\n    Some Content\n{% endblock %}\n\n{% block footer %}\n    {% include 'includes/custom-footer.html.twig' %}\n{% endblock %}\n```\n\n```twig\n{# templates/pages/child.html.twig #}\n\n{% block header %}\n    {% include 'includes/header.html.twig' %}\n{% endblock %}\n\n{% block content %}\n    \n{% endblock %}\n\n{% block footer %}\n    {% include 'includes/footer.html.twig' %}\n{% endblock %}\n```\n\n### Include and override parts (Twig 🌱) (using embed)\n\n```twig\n{# templates/pages/parent.html.twig #}\n\n{% embed 'includes/child.html.twig' %}\n    {% block header %}\n        {% include 'includes/custom-header.html.twig' %}\n    {% endblock %}\n    \n    {% block content %}\n        Some Content\n    {% endblock %}\n    \n    {% block footer %}\n        {% include 'includes/custom-footer.html.twig' %}\n    {% endblock %}\n{% endembed %}\n```\n\n```twig\n{# templates/pages/child.html.twig #}\n\n{% block header %}\n    {% include 'includes/header.html.twig' %}\n{% endblock %}\n\n{% block content %}\n    \n{% endblock %}\n\n{% block footer %}\n    {% include 'includes/footer.html.twig' %}\n{% endblock %}\n```\n\n### Include and override parts (Explanation)\n\nIn Twig there are different solutions for this kind of task.\nWhere mostly you would work in Twig with `extends` from a\nspecific `base.html.twig` and maybe have 1-3 different kind\nof this base template, its very uncommon in Twig that you\ninclude a component template and override a part of it.\n\nMostly Twig devs will go here with a additional Twig template\nand use `extends` and in the other template an `include` tag\nto the new template.\n\nTwig provide with the `embed` tag here to combine a `include`\nand `extends` in one template and avoid so the additional\ntemplate.\n\nAs this pattern is very uncommon you should not overuse the\n`embed` tag as it make the templates unreadable.\n\n## Dynamic Include\n\nThere are cases mostly when working with some kind of block\neditors where you would need to have an own component / template\nfor every block type your block editors does provide.\n\n### Dynamic Include (React JS ⚛️)\n\nIn react this kind of things would need additional services\nand some kind of registry to be this dynamic. I will currently\nnot provide an example and just show in the next step how it\nwould be done in twig.\n\n### Dynamic include (Twig 🌱)\n\n```twig\n{# templates/pages/default.html.twig #}\n\n{% set blocks = [\n    {\n        \"type\": \"text\",\n        \"title\": \"My Title\",\n        \"description\": \"My Description\"\n    },\n    {\n        \"type\": \"quote\",\n        \"quote\": \"My Quote\",\n    }\n] %}\n\n{% for content in blocks %}\n    {% include 'includes/block-types/' ~ block.type ~ '.html.twig' %}\n{% endfor %}\n```\n\n```twig\n{# templates/includes/block-types/text.html.twig #}\n\n\u003cdiv class=\"text\"\u003e\n    \u003ch3 class=\"text-title\"\u003e{{ content.title }}\u003c/h3\u003e\n\n    \u003cp class=\"text-description\"\u003e{{ content.description }}\u003c/p\u003e\n\u003c/div\u003e\n```\n\n```twig\n{# templates/includes/block-types/quote.html.twig #}\n\n\u003cdiv class=\"quote\"\u003e\n    \u003cblockquote\u003e{{ content.quote }}\u003c/blockquote\u003e\n\u003c/div\u003e\n```\n\n### Dynamic Include (Explanation)\n\nIn twig as you can just concat the string and include a template\ndynamic you don't need any additional registry or other service\nto map between the block type and template. And as by default\na included template as access to the parent variables you are also\nnot force to map all properties from the parent template to the\nchild template as the child template can just access it.\n\nIf you still want todo that you could go with something like:\n\n```twig\n{% for block in blocks %}\n    {% include 'includes/block-types/' ~ block.type ~ '.html.twig' with {\n        content: block,\n    } only %}\n{% endfor %}\n```\n\n## Conclusion\n\nTwig and React JS (JSX) are in some cases very similar how they\nrender and output things. Twig is really focused of just creating\nHTML or the outputted file format, like what `JSX` was designed for.\n\nWhere in `React JS` you have access to all JavaScript functions,\n`Twig` is very strict here as it is designed that all your Business Logic\nlives in your PHP code before Twig is callded.\nSo if your Twig code begins to look messy or you have a lot of logic\nstatements in it, it is a hint that you did accidentally move your \nBusiness Logic which should be handled in your PHP Controller\ninto your template rendering, which should be avoided.\n\nI hope with this article I can give React Developers an easier\nway to get into Twig.\n\nFor getting an overview of all available Twig functionality I recommend\nto read over the [Official Twig Documentation](https://twig.symfony.com/).\n\nThank you for reading this!\n\nMore articles on Github from me can be found [here](https://github.com/topics/alexander-schranz-article).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexander-schranz%2Ftwig-for-react-devs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falexander-schranz%2Ftwig-for-react-devs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falexander-schranz%2Ftwig-for-react-devs/lists"}