 All right, afternoon, everyone. Thanks for coming along to this session. Today, we're talking about View3 for React developers and vice versa. I know previously I've made fun of sessions that start by asking people to have a show of hands. But if we could have a show of hands, who would class themselves as a React developer? And who would class themselves as a View developer? All right, this is a pretty dry session. So what I'm going to get you to do is can we get the React people on this side? And the View people on this side. So we're going to assume that you're comfortable with React or View or at least have some familiarity with the front-end framework and what they're for. We're going to look at the Composition API in View. Now, if you're a React developer, don't really worry about that. We'll get to that. There's a few different ways to do things in View. There's the Compositions API and the Options API. We're only going to look at the Composition API. We're only going to look at single file components. And we're only going to look at the script setup, syntactic sugar. If you're familiar with the other parts and your View developers, maybe talk to them after the session to see what they're about. But we're trying to compare where the two are the same here. And those are probably the closest. The Composition API is closest to React. Also, bear in mind that you can add JSX support for View, which gets it even closer to React. But we're not going to do that here. And there is going to be a lot of code because we're going to do some comparison between the two. And we're going to compare and contrast as we go. So some quick background. View was created by Evan Yu in 2014. And the latest version is version 3. The version 2 to version 3 transition is probably analogous to the Drupal 7 to Drupal 8. It's quite a large upheaval for the View community. And it's a community-driven open-source project with funded by sponsorships, much like Drupal. And that's the last time I'm going to mention Drupal for this whole session. It's MIT License. React, on the other hand, started at Facebook. And most of the core developers are still employed by Meta. It was originally a pseudo open-source license. So there was a non-compete clause, but that's since been removed and it's now a genuine MIT license. So the current version of View is about a 16K kilobytes baseline. But if you have used every single feature, and you probably won't, it's around 27K. And it does do tree shaking when you build. So it does throw away the things that you're not using. On the other side, React is about 137 kilobytes. If you're using the browser, you need React and React DOM. So it's quite a larger footprint. The current version of React is 18, and that was released, the first version was released in 2013. And if you do want to know more about the origins of these two frameworks, I encourage you to look up the Honeypot channel on YouTube. They've done some excellent documentaries about the origins of lots of different open-source technologies. And they've got 30-minute documentaries about both of these that are really interesting. But to get started, there's lots of different ways to do it. But what we're going to talk about today is just using VIT, because you can use it for both. For those not using it in VIT is a NPM, does NPM module resolving, pre-bundling, it's a dev server, does hot module reloading, and it supports TypeScript and JavaScript, JSX out of the box, CSS, Post-CSS, CSS modules, many things. So to get started with React, you would just run NPM, create VIT at latest, minus, minus, template is Vue for Vue, and minus, minus template is React for React. So up to this point, we're pretty much the same. Let's have a look at a Hello World example for Vue, and hopefully that renders okay under the light. Ah, sorry for React. So we've got a React functional component here, we're not going to use class components, they're the old way of doing things. You normally have to import React for the compiler's sake, but we're going to ignore that as well. So your props for your component are passed in as the first argument to the function. We're using array destructuring here to grab the message prop out of the properties, and you can see we're rendering that in a H1 using the single mustache brackets. Henceforth, I'm going to refer to them as muzzies. So single muzzies. A React element must have one component at the root, you can't have two elements. So you can see here we've got, it looks like an empty tag, and that's called a fragment in React, and so you can wrap your whole component in that to get that equivalent of the root element. And at the end here, we're just exporting a function, and then you can use that function in other places. By default, there's no typing of the props, you can use a package for that, and we'll talk about that later. Now let's have a look at the Vue equivalent. So the big difference that you notice is there's some wrapping elements, there's a template element at the root, and then there's a script element. So your JavaScript goes inside the script element, we've got the setup keyword there, which does make things a lot simpler, and another distinction is there's double muzzies to output your variables, so this is much closer to twig if you're familiar with twig. We also have to use this define props function to tell Vue what the props available are, and here we're saying message, it's type string, and it's required true. And we'll talk about that a bit more once we get further into it. Again, mounting your application, once you've built something, you want to actually use it in the browser. On the React side, you need to get React DOM and React. You create a root by passing it a DOM element, and then you call render with the component that you want to render into that HTML element. On the Vue side, it's very similar, it's a little bit more succinct, so you import create app, you call create app for the app component, and then you call mount, and you just pass it a DOM selector, so it handles the query selector for you. And when you get to definition of props, I mentioned before that React doesn't have strict typing out of the box unless you're using TypeScript, and so you can use a prop types package, you install that, and then you can put a prop types static property on your function and tell it, for example here, there's a person name prop, you can see the component outputs high person name, and we're saying that that has to be a string and it is required, and you'll get warnings throughout your compilation and in the console in development mode if you're passing the wrong thing. So before on the Vue side, you had to declare it, but some other things you can do in Vue that are not as simple to achieve in React is you can actually make a validation function, so you can have a dynamically return whether or not the prop pass is valid. And one thing to notice with this default Johnny, that works fine for statics, but for arrays and objects, you have to have a function there that returns, so like a factory function basically. When you go to render your components, this is the React example. So we've got a component here called sum parent, it takes a prop called person name, and then we're creating like a pojo, plain old JavaScript object with the person name property, and there's three different ways here to render my component, which takes a person name. The first one, we're passing a static string Bessie, and that will never change. We're using six double quotes there. The second one, we're using a variable, so person name is the variable being passed in as the prop and we're using single muzzies there and no double quotes. And then the third one, we're using an object where the object properties align to the props of the component and you can just use the single muzzies and then there's like the spread operator. On the view side, it uses kebab case for its props, so you can see down the bottom here, we've got person name with the capital N, but up the top, it's more HTML like person dash name. And again, here's the same three examples, so static string is in double quotes, and this is where the things get a bit interesting in view land. If you wanna use a variable, you put a colon in front of the prop and the JavaScript, it recognizes what's in between the double quotes as JavaScript and so that knows to use the person name prop. You'll also note that I've admitted the defined props here from the previous slide, but that person name is defined ahead of time. And then the last one, vbind is equivalent to the third example over there. So if you have an object where all the props have the same names as your component, you can just use vbind. When you're rendering one of these component elements, you'll always wanna have some sort of children. So say for example, you've got a h1 that wraps some child elements or a div, for example. So in React's case, there's a special prop called children and that will give you a node or a tree of nodes that you can just output with the single muzzies. And so the second example here, we can see, yeah, we've got my component being rendered and we're passing in a P with this as a child. And so in the my component, you can see that comes like the P this is a child is the children. On the view side, however, you have to use the special slot component. So this is the my component equivalent, which is kinda like the div with the children over there. So in place of the children, we have slot. And so one thing that view has that React doesn't have here is, sorry, this is how you use that. So you would say P this is a child and the P this is a child ends up being output where slot was. But with view, you can have multiple slots and you can name them. So consider like a typical layout where you've got a header and a main in the side. You can have three name slots there. And then to render that, you have the template meta element and you can say V slot colon the name of the slot. So this is something that view has is a little bit stronger than React. It doesn't have, yeah, you can actually have multiple child elements here. So it's a quick temperature check. Is there anyone who was in the React camp that is now view curious or vice versa? Shall hands anyone? Yeah, there's a few. Okay, that's good. And I'm putting these in here because as I said, there's a lot of code and this is very dry. So control structures, conditionals, when you're rendering a component, you're probably gonna wanna have some sort of logic. That's the whole point of these. In React, you can just use raw JavaScript and you just have to escape it with the curly brackets. So you can see here inside our component, we've got plain JavaScript, if age is greater than 18, we return something and then we've got another code path that returns something else. And we can also see there, we're using member and and. So inside the single muzzies, you can put JavaScript logic. And so the span with the lock on it will only render if member is true. And one thing to note here is that member, you know, it has to be a Boolean. So you can't use array. You need to use array.length greater than zero and things like that. It has to be an actual Boolean. On the view side, it's a little bit angular-like. You have the special directives vif, velse. So this is equivalent code between the two. You don't need the colon before the attribute name like we did before. It always assumes that what's in vif and velse is gonna be JavaScript and we'll execute it. So if age is greater than 18, you say hi, person name and same high name with a span. I guess that's the main difference here that we had to have the span element there. Over on the react side, we could use one of those empty fragments and I'm assuming over here we could use the same. And again, yeah, we've got to define the props here. So we're saying name is a string, member is a Boolean and age is a number. Probably gonna want some loops as well. So on the react side again, we open up the single muzzies and we can just use raw JavaScript. We have a map here and the return from the map is a list item and that gets rendered. And one thing to note here, we have to have a key. So when the react renderer is doing a diff, you see what's changed. You know, it uses that key to uniquely identify child elements to know which ones to update and render. On the view side, it's not surprisingly a special directive we've got. Here is the v4. So again, we've inside the maps, we're using a list item. Over this side, the list item has that v4 attribute on it and yeah, you declare the variable name. So item in items is kind of like the argument for the array function we've got over there inside map. And similarly, you need a key and for the same reasons. And you see here, we've got items as type array. Okay, so the whole point of these components is to be able to track some sort of state. If not, you probably just use raw HTML. So on the react side, we have a hook called use state and that returns a tuple or a tuple, depending on how you pronounce it. You pass in the default value so zero is the default value here and every time you click the button, you're gonna wanna increment that. You notice that you've got both a value and a setter. On the view side, you use something called a ref. So if you're coming from React, you're probably familiar with use ref and this is where it gets a little bit confusing but a ref is like a dynamic variable, I guess is the simplest way to put it. You'll notice here, yeah, I've imported the ref function, creating a ref value of zero and we've got the counting output. So again, this is equivalent code. Now, there's no real point in having the state unless when you click on this, well, div's not the right thing, but when you clicked on a button, the count would increment. So you're gonna want some sort of event. So on the react side, we just put an on click and you'll notice it's on click with the capital C instead of on click with the low C. The reason behind that is the event system in react is synthetic and that's a whole not the talk on its own that we're not gonna get into. So on click here, we've just got an array function, sorry, an arrow function and we're calling set count which is the setter that you state gave us and we're incrementing the count. On the view side, you use the at click attribute and in that you put the name of function. So we've declared our function down the bottom here and you'll notice here, I'm working with count dot value. So there is no setter with refs. You just access the dot value and you mutate that directly and if those are interested in the information under the hood, it's kind of like a user's a JavaScript proxy, which is a little bit like, you know, the magic underscore set function in PHP and that actually takes care of mutating things under the hood. But one thing a few has that react doesn't is you can actually had modifiers to things. So I can say at click dot prevent and that will call the increment that'll also call event dot prevent default. So you can do a lot of those browser primitives. There's specialized versions of the attribute that will give you so there's a prevent default. There's a bubble, for example. And it also supports emitting events. So if you've ever worked the react before, you'll know that if you need, you know, if you declare the state in a parent component of this component over here and you want this component to update the on click, then you have to pass in the handler as a prop and then the on click is set to the prop. So the parent maintains a state and passes down the event handler to the children in view. You can work things the other way. So you can say define emits and that means there's a new event called update. And so inside your increment function, you can admit an update. And so this is kind of, I know I said I wouldn't talk about Drupal but kind of like, you know, module invoke all type equivalent or, you know, in native JavaScript it's just, you know, dispatching an event. And in your parent component, you can have at update. So that's the name that you gave the emit. And so that update will call handle update. So this is how you can bubble events from the child up to the parent. Okay, another temperature check. Anyone else interested in changing sides or changing allegiance or at least having a bit of a look at the opposition here. Yeah, okay, we've seen a few more hands. All right. So styling. With the React you can have global styles and you import, you know, styles.css and the build process makes sure that that gets output as a style tag for you. You can also use CSS modules for scope styling. And in that instance, so see here we've got class name equals lead. If you were to import that with CSS modules like this, you have like an object and you class, you'd use as this camel case here. So you probably would have had that as dot some dash style in your CSS file and it becomes styles dot some style here. And you notice, yeah, class name instead of class because, you know, JavaScript, a JSX is a mix of, you know, HTML and JavaScript and class is a reserved word in JavaScript. React also has a multitude of CSS in JavaScript libraries like Emotion, style components, vanilla extract and they're all trying to make things easier to manage for your styles. View on the other side has scope styles out of the box. So we had the template tag, we had a script tag, and you just add a scope style tag to your component and you put the scoped key word on it. So dot some style in this class is different to dot some style in another component. And again, it's just class, not class name. I'm gonna start speeding up a bit because I think I'm gonna run out of time, but data binding. So if you're building a form element in React, you would put a value attribute. And so on your input element here, you've got value equals text and that's the sign to a variable. And then if you wanna update the value of text, you have to have an unchanged listener, again the C's capital, and you call your set state, which is the setter for your state and set the value. I notice also HTML4 there because 4 is a JavaScript reserved word. With you, you use v-model and it keeps your value in sync. So we created a ref for text and we said v-model is text up there. And every time you type something into that text box, it'll automatically update text for you that you have to input the event handler like it did on this side. Data fetching. Now this is very primitive. If you're doing this for real, you'd probably want bought handlers and loading state and error handling, et cetera. And you're probably best to use a library like tans.query and if you're interested in that some more Jack Taranto did a session on that at the previous Drupal South. So on the React side, we use something called use effect, which is a hook. Talking about use effect is probably a whole session on its own, but let's just, for simplicity sake, say the second argument to use effect controls when it runs and passing an empty array tells it to only run when the component is first mounted. So what we're doing here is when the component mounts, we'll do an async fetch call and return some users and then from that we'll set data. And then down below in our, where we're returning the markup from the component, we've got one of those and ands inline there. And so if there's data length greater than zero, outputting a list of the users using map like we were before. On the view side, it's pretty similar. So, but we can actually put this straight in our script. So this will mount as soon as it mounts, it will fetch and I'll update. And again, we're using data.value for our setter and when that async call has finished, view will re-render and the list will be output. So we've got equivalent kind of control structures. We've got v4 in place of the map. We've got vif in place of the conditional at the front. It's like one of my curly braces ended up on the next line there. I think we've done enough temperature checks. Okay, so global state. We don't really have enough time to go into global state management in detail. We saw some use state and ref things before. And obviously in any app of any sufficient complexity, that's not going to scale and you're going to want to look at some sort of global state management. In React, there are two hooks out of the box, use reducer and use context. And they let you sort of wrap your components in a context provider and the context provider lets you access state from parent components without having to pass the props down. Something called prop drilling. But at some point that starts to become too complex as well. And that's where something like Redux comes in, which is a whole library for state management. And on the view side, there's a equivalent called Pinnier. So Pinnier is a state management library for view. And personally, I've found it easier to work with. It felt like there was a lot less boilerplate, but Redux Toolkit is an extension on top of Redux that does give very similar developer ergonomics to Pinnier. And I think both of these are worth investing some time in if you're building anything of sufficient complexity. Next thing you might want to do are DOM references. So I know we had a ref in view before and I talked about use ref. So use ref is a hook that will guarantee you the same value between renders. And in this instance, we can put a ref attribute on an input. So use ref, start with null and then we put the ref attribute. And every time this component renders, ref.current will be a reference to the DOM node. So you can use DOM APIs like ref.current.focus, for example. On the view side, before we said you use ref for state, you also use ref for use ref. It gets a bit confusing, but I guess it's one tool for both. And same, you declare your ref like you did before with state and you set ref equals input just like we did over this side. And yeah, you can access it with dot value, which was consistent with all the other view code. Whereas over this side, it's dot current. The next thing you probably might want to do something with is component lifecycle. So I talked before about use effect and I said I won't go into much detail. We saw before if you pass an empty array as a second argument, it'll render on mount. So the do something on mount code there will run. But you can also return an arrow function from that or like a function from that and that function gets called when the component gets cleaned up. So you can do something on unmount. On the view side, it's a lot more explicit. There's two hooks that you import on mounted and on unmounted and you declare your callback for those. There's a lot of jokes and et cetera on the internet about use effect. Not as many as about exiting Vim, but getting close. So this is a little bit nicer. Oh yeah, so that's the summary. Here's a link to the slides if you want to refer back to any of this because I'm aware there's a lot of code on there. So yeah, I hope you saw from this that there's a lot in common. And I hope you would think if you re-asid this or went back to it, you could translate a concept from one that you're familiar with to the one that you weren't familiar with. And I'm interested in what people think about what they prefer. And probably the million dollar question is which one do I prefer, which I haven't really alluded to until this point. And for me, Vue has a lot of nice developer features. And as you saw, several things like forms and data fetching and styling, they just feel easier. But conversely, React, the ability to just use plain JavaScript inside your component for things like list items and conditionals feels a little bit less magic than the attributes like VIF and V4. So to give a, yeah, I'm not really, I'm not gonna commit to an answer. Yeah, I think I like both of them. And I think as part of, in our role as modern web developers, I think it's important for you to know the strengths and weaknesses of both, just like you would with Drupal modules. And yeah, as I mentioned before, the size of Vue versus the size of React could be a telling feature in your project, depending on what you're dealing with. And there are like lightweight versions of React like Preact, which are largely the same, but a much smaller sort of download size. But yeah, I think we've got some time left for questions. So shout out to Pimple. So for the recording, Jibran pointed out, you can use Pimple, is it as well as Redux or instead of Redux? Instead of Redux, which has less boilerplate. I have to have a look at it. And yeah, as always, I'm on Slack. Feel free to ask me questions if you think it's something after the event. All right. Cheers, thank you. Thank you.