Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce UX React component #329

Merged
merged 1 commit into from
Jun 6, 2022
Merged

Introduce UX React component #329

merged 1 commit into from
Jun 6, 2022

Conversation

tgalopin
Copy link
Contributor

@tgalopin tgalopin commented Jun 2, 2022

Q A
Bug fix? no
New feature? yes
Tickets -
License MIT

This PR introduces a new component called UX React. This UX component creates a bridge between Symfony and React by allowing Twig developers to render React components, passing data smoothly between the two.

After installing this component, it is possible to use the react_component Twig function to render a React component in a specific HTML container:

// assets/react/controllers/MyComponent.jsx
import React from 'react';

export default function (props) {
    return (
        <div>Hello {props.fullName}</div>
    );
}
{# templates/home.html.twig #}

<div {{ react_component('MyComponent', { 'fullName': app.user.fullName }) }}></div>

This behavior works by allowing UX React users to register React components in a global key-value store that is then used by a generic Stimulus controller (Resources/assets/src/render_controller.tsx) to do that the actual rendering. I propose to introduce a assets/react/controllers directory to automatically register all components inside this directory, to ease usage. You can read the README for more details.

This component supports Symfony 4.4+ (super simple bundle, no reason not to be IMO) and React 16+ (released in 2017).

Copy link
Member

@weaverryan weaverryan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WONDERFUL!

src/React/README.md Outdated Show resolved Hide resolved
src/React/README.md Outdated Show resolved Hide resolved
// By putting only controller components in `react/controllers`, you ensure that
// internal components won't be automatically included in your JS built file if
// they are not necessary.
registerReactControllerComponents(require.context('./react/controllers', true, /\.(j|t)sx?$/));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We MAY soon get the ability to do simple "patches" in Flex. If so, this could be added to a recipe.

src/React/Resources/assets/package.json Outdated Show resolved Hide resolved
src/React/Resources/assets/src/render_controller.ts Outdated Show resolved Hide resolved
src/React/Resources/assets/src/render_controller.ts Outdated Show resolved Hide resolved
src/React/Twig/ReactComponentExtension.php Outdated Show resolved Hide resolved
src/React/composer.json Outdated Show resolved Hide resolved
@tgalopin tgalopin force-pushed the ux-react branch 3 times, most recently from 023437f to c52e713 Compare June 3, 2022 12:05
@tgalopin
Copy link
Contributor Author

tgalopin commented Jun 4, 2022

Updated after reviews. I dropped support for React 17 and less (not worth it indeed).

The PR is ready I think!

@weaverryan
Copy link
Member

Thank you Titouan!

@weaverryan weaverryan merged commit f1711ec into symfony:2.x Jun 6, 2022
'use strict';

import React, { ReactElement } from 'react';
import { createRoot } from 'react-dom/client';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm, actually this is proving problematic. I merged, thinking the yarn build failure was something unrelated, but it's not. yarn build fails here with:

Error: 'createRoot' is not exported by node_modules/react-dom/client.js, imported by src/React/Resources/assets/src/render_controller.ts

That is not correct... as createRoot IS an export of that file. I'm not sure if we may need commonjs for rollup (https://rollupjs.org/guide/en/#error-name-is-not-exported-by-module... also ref similar issue: JedWatson/react-select#3956 (comment)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like I fixed it over here: #330

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great! I was going to have a look :)

@tgalopin tgalopin deleted the ux-react branch June 6, 2022 16:26
tgalopin added a commit that referenced this pull request Aug 22, 2022
This PR was squashed before being merged into the 2.x branch.

Discussion
----------

[Vue] Introduce Vue UX component

| Q             | A
| ------------- | ---
| Bug fix?      | no
| New feature?  | yes <!-- please update src/**/CHANGELOG.md files -->
| Tickets       |  N/A <!-- prefix each issue number with "Fix #", no need to create an issue if none exist, explain below instead -->
| License       | MIT

<!--
Replace this notice by a short README for your feature/bugfix. This will help people
understand your PR and can be used as a start for the documentation.

Additionally (see https://symfony.com/releases):
 - Always add tests and ensure they pass.
 - Never break backward compatibility (see https://symfony.com/bc).
 - Features and deprecations must be submitted against branch main.
-->

This PR introduces a UX Vue component which allows to render Vue.js components inside Twig templates, with the ability to pass down props to Vue components from Twig. It is implemented in the same way as the UX React component for coherence.

1. Call `registerVueControllerComponents`  in `app.js` to register Vue components

```js
import { registerVueControllerComponents } from "`@symfony`/ux-vue";

registerVueControllerComponents(require.context('./vue/controllers', true, /\.vue$/));
```

2. Create Vue "controller components" (eg. `Hello.vue`) inside the folder specified above (here `assets/vue/controllers`)
```vue
// assets/vue/controllers/Hello.vue
<template>
    <h1>Hello {{ name }}</h1>
</template>
```
3. All those components can now be used inside Twig using the helper function provided by the bundle, the second parameter are props that will be provided to the component
```twig
<div {{ vue_component('Hello', { name: 'Thibault' }) }}></div>
```

The implementation was **heavily** inspired by the work from `@tgalopin` in #329 (that's why I left him as author everywhere).

I'll gladly write docs and ux.symfony.com samples if accepted and once we agree on the API.

NB: Only Vue.js v3 is supported

Commits
-------

ff95c1a [Vue] Introduce Vue UX component
@kingjulien1
Copy link

is there a way to pass children to a react component? for example like this:

// assets/react/controllers/MyComponent.jsx
import React from 'react';

export default function (props) {
    return (
        <div>
              <h1>heading</h1>
              {props.children}
        </div>
    );
}
{# templates/home.html.twig #}

<div {{ react_component('MyComponent', { 'fullName': app.user.fullName }) }}>
    <p>content to be displayed inside the react component}</p>
</div>

or, if not, is there a workaround to achieve this functionality?

@weaverryan
Copy link
Member

Could you open a separate issue? We COULD do this - in the Stimulus controller, we could read the innerHTML of the element and make it available as props.children via dangerouslyInnerHtml (we would make this opt-in - so we would need some sort of new option to enable this).

@seb-jean
Copy link
Contributor

seb-jean commented Oct 8, 2022

How can Symfony forms be used with this component?

@weaverryan
Copy link
Member

What exactly would you want to accomplish?

@seb-jean
Copy link
Contributor

The idea is to click on a button, it opens a modal with the form in react.
For example a password change form.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants