These days, a new trend front end framework is released every once in a while. But React and vue.js remain the most popular of all the other alternatives.

Although both frameworks are high-performance, elegant, and arguably easy to learn, they have a slightly different view of how certain things should be done, and different ways to achieve the same end result.

I believe the comfort and efficiency of using a front-end framework is mostly about learning patterns to do regular things.

You know how to listen for a parameter/data change and do something about it. And how to bind event listeners or data to an action object (buttons, check boxes, and so on).

When I was doing a side business with React, I noticed that my thoughts went something like this.” Yes, I can do that in Vue, I’ll issue an event from the child, then listen for it on the parent side and update this data. Then I googled how to do something like this in React.

In this article, I’ll show you how React and Vue apply some common patterns that you’ll encounter in your daily front-end work. You can then use these recipes to easily transition from one frame to another.

This will help whether you’re an experienced Vue developer who needs to work on the React project or vice versa. I’ll use the modern React hooks and Vue option API (Vue 2).

I recommend cloning the repository that contains all the code I use in this article and rendering the individual components in each section to play around with them to really understand how they work.

After cloning, you need to run NPM Install in the React and Vue folders. Then you can start the React project with NPM start and the Vue project with NPM Run serve.

https://github.com/yigiterinc/VueVsReact
Copy the code

Making a link

directory

  • React and Vue component structures
  • How do I use states in React and Vue
  • How to use items in Vue and React
  • How to create methods/functions in Vue and React
  • Styles to choose
  • How do I bind form input to data (state)
  • How to handle events (user input
  • Conditional modeling
  • Conditional rendering
  • Render an array (list)
  • Communication between son and mother
  • Response to data/state changes
  • Calculate attributes and use memos
  • Vue Slots vs Render Props

Component structure

Let’s take a bird’s eye view of some very basic components in both frameworks. We will expand on this in the following sections.

In Vue, a single-file component consists of three parts: templates, scripts, and styles.

The template is the part that will be rendered. It contains the HTML of the component and has access to the data (and methods) in the script and style.

You can find all about a component in these sections of Vue.

<template>
  <div id="structure">
    <h1>Hello from Vue</h1>
  </div>
</template>

<script>
export default {}
</script><! -- Use preprocessors via the lang attribute! e.g. <style lang="scss"> -->
<style>
#structure {
  font-family: Avenir, Helvetica, Arial, sans-serif;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>
Copy the code

To render this component without routers or other complications, you can add it to app.vue. I recommend that you render each component as you follow along, so you can see them in action.

<template>
  <div id="app">
    <structure />
  </div>
</template>

<script>
import Structure from './Structure/Structure.vue'

export default {
  name: 'App'.components: { Structure },
}
</script>
Copy the code

App.vue

You will change the label name of the import component and template section of the component section.

In React, the feature component is a function that returns JSX (a JavaScript extension that allows you to use HTML tags in JS code). You can think of it as returning HTML to simplify things. If you’re familiar with class-based React, the part that will be rendered used to be written inside the render() function.

As you progress through this tutorial, in each section you can put the individual components in app.js and have them rendered like this.

import React from 'react'

function Structure() {
  return <div>Render me App</div>
}

export default Structure
Copy the code

component

import './App.css'

import Structure from './Structure/Structure'

function App() {
  return (
    <div className="App">
      <Structure />
    </div>)}export default App
Copy the code

App.js

So you’ll change the components inside the import and div.

How to use state

In Vue, we learned that script tags contain component-specific data and methods. The Vue options API has special keywords (options) such as _ data, methods, props, calculations, observation _ and _ mixer _ that we can use, as well as lifecycle methods such as _ create _ and _ load _.

We will use the data option to use state in our component. Data should be defined as a function that returns an object containing our state.

To access the state in our HTML (template), we must use double curly braces and write our variable name. Remember that if a data variable is used (referenced) in HTML, any changes to that variable will result in rendering.

<template>
  <div>
    <h1>Hello {{ currentFramework }}</h1>
  </div>
</template>

<script>
export default {
  data() {
    return {
      currentFramework: ' Vue! '.alternative: ' React! ',}}}</script><! -- Use preprocessors via the lang attribute! e.g. <style lang="scss"> -->
<style></style>
Copy the code

UsingState.vue

In React, feature components used to be stateless. But thanks to hooks, we now have useState hooks to store state within our component. To use the useState hook, we must import it, whose syntax is.

import React, { useState } from 'react';


function App() {
    const [stateName, setStateName] = useState('default value'); 
}
Copy the code

UseState grammar

We define the name of the state variable and the name of its setter function in parentheses, and we pass the default value of our variable to the useState hook.

You can visualize the hook this way to better understand the syntax. It is like a function that creates a variable, sets its value to the passed value, and then returns an array containing the variable and its setting function.

Note that you should use a pair of curly braces to switch to a JavaScript scope and print a variable in your JSX instead of using double braces, as Vue does.

import { React, useState } from 'react'

function TestUseState() {
  const [frameworkName, setFrameworkName] = useState('React')

  return (
    <div>
      <h1>useState API</h1>
      <p>Current Framework: {frameworkName}</p>
    </div>)}export default TestUseState
Copy the code

How to Use items

In Vue, we define props by adding the props option to the exported object in the script field, just as we did with the data option. It is best to define items as objects so that we have more control over how they are used.

For example, specify their types, default values, and make them mandatory if necessary. Vue displays a warning if you use this component incorrectly, such as calling it without passing the necessary items.

Suppose we have an Address child that will be called from the UserInfo parent.

<template>
  <div class="address">
    <p>City: {{ city }}</p>
    <p>Street: {{ street }}</p>
    <p>House No: {{ houseNumber }}</p>
    <p>Postal Code: {{ postalCode }}</p>
  </div>
</template>

<script>
export default {
  data() {
    return{}},props: {
    city: {
      type: String.default: 'Munich',},street: {
      type: String.required: true,},houseNumber: {
      type: Number.required: true,},postalCode: {
      type: Number.required: true,,}}}</script>

<style></style>
Copy the code

Child component (address.vue

We can access our props as if they were data variables — using double brackets inside the template. And we can pass items from the parent component like this.

<template>
  <div class="address">
    <p>Name: Yigit</p>
    <Address
      street="randomStrasse"
      :postalCode="80999"
      :houseNumber="32"
    ></Address>
  </div>
</template>

<script>
import Address from '@/components/Address.vue'

export default {
  data() {
    return{}},components: {
    Address,
  },
}
</script>

<style></style>
Copy the code

The parent components (the UserInfo. Vue)

Notice how we use v-bind shorthand: and write :postalCode and :houseNumber to indicate that these are not strings, but objects of type Number. We have to use this syntax whenever we need to pass anything other than strings (arrays, objects, numbers, and so on).

This can be confusing if you’re from React, so you might want to read more about V-bind to better understand how it works.

In React, we don’t need to explicitly define which items will be passed to the child components. We can use object destructor to assign items to variables, or use item objects to access them. We access our props inside JSX, just like we access state.

import React from 'react'

function Address({ city, street, postalCode, houseNumber }) {
  return (
    <div>
      <p>City: {city}</p>
      <p>Street: {street}</p>
      <p>Postal Code: {postalCode}</p>
      <p>House Number: {houseNumber}</p>
    </div>)}export default Address
Copy the code

Child components (Address. Js)

And we can pass props from the parent component like this.

import React from 'react'

function UserInfo() {
  return (
    <div>
      <p>Name: Yigit</p>
      <Address
        city="Istanbul"
        street="Ataturk Cad."
        postalCode="34840"
        houseNumber="92"
      ></Address>
    </div>)}export default UserInfo
Copy the code

The parent components (the UserInfo. Vue)

How do I create methods/functions

In Vue, we define methods in a similar way to data — we can put a method option under the data and define methods. We can call these methods from the template, and the methods can access/modify our data.

<template>
  <div>
    {{ sayHello() }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      to: 'Methods',}},methods: {
    sayHello() {
      return 'Hello ' + this.to
    },
  },
}
</script>

<style></style>
Copy the code

sayHello.vue

Be careful when trying to access component methods or data properties from within the exported object (the code inside the script tag). If you don’t include the this keyword, Vue will display an error saying it doesn’t know where that property/method is.

In React, things are simpler. It’s just a regular JS function definition, using ES6 syntax if you want.

import React from 'react'

function HelloFunctions() {
  const to = 'Functions'

  function sayHello() {
    return 'Hello ' + to
  }

  const sayHelloModern = () = > 'Hello ' + to

  return (
    <div>
      {sayHello()}
      <br />
      {sayHelloModern()}
    </div>)}export default HelloFunctions
Copy the code

SayHello.js

Stylize options

The styling of Vue components is really simple. We just need to put our normal CSS classes and selectors in the Style tag.

Vue also supports scoping control of CSS using the scoped keyword. It helps avoid the visual error of assigning the same class name to different components. For example, you can name the main container main-container in all of your components, and only the styles in that component file will be applied to each main container.

<template>
  <div class="main-container">
    <h3 class="label">I am a styled label</h3>
  </div>
</template>

<script>
export default {
  data() {
    return{}}},</script>

<style scoped>
.main-container {
  position: absolute;
  left: 50%;
  top: 45%;
  margin: 0;
  transform: translate(-50%, -50%);
  text-align: center;
}

.label {
  font-size: 30px;
  font-weight: 300;
  letter-spacing: 0.5 rem;
  text-transform: uppercase;
}
</style>
Copy the code

Styling.vue

In React, we have more options in styling, and it’s basically up to your personal preference, because there are multiple ways to design your components. I’ll suggest a few good options here.

1) Write regular CSS in a.css file and import it

This is probably the most basic and straightforward way to style your React component. That doesn’t mean it’s a bad method, because it allows you to write plain old CSS. If you’re a CSS guru just starting out with React, this is a great way to do it.

import React from 'react'
import './styles.css'

function Styled() {
  return (
    <div>
      <h3 class="title">I am red</h3>
    </div>)}export default Styled
Copy the code

Styled.js

.title {
  color: red;
  font-size: 30px;
}
Copy the code

styles.css

2) Use Material UI (useStyles/makeStyles)

Material UI is a CSS framework with many reusable components. It also provides a way to style your components, and it uses CSS in JS, so it has its advantages such as scoped CSS.

The makeStyles hook receives a list of classes in an object, which you can then use by assigning them to the object.

import React from 'react';
import { makeStyles } from '@material-ui/core/styles';
import Button from '@material-ui/core/Button';

const useStyles = makeStyles({
  root: {
    background: 'linear-gradient(45deg, #FE6B8B 30%, #FF8E53 90%)'.border: 0.borderRadius: 3.boxShadow: '0 3px 5px 2px rgba(255, 105, 135, .3)'.color: 'white'.height: 48.padding: '0 30px',}});export default function Hook() {
  const classes = useStyles();
  return <Button className={classes.root}>Hook</Button>;
}
Copy the code

3) Use stylized components (CSS in JS)

Styling components are modern and easy to use, allowing you to take advantage of all the functionality of normal CSS.

In my opinion, it is easier to use and more powerful than MaterialUI (you can also use it to style MaterialUI components instead of using makeStyles). It is also better than importing a CSS file because it is scoped and the styled components are reusable.

import React from 'react'
import styled, { css } from 'styled-components'

// Use Title and Wrapper like any other React component – except they're styled!
const Title = styled.h1` font-size: 2em; text-align: center; color: palevioletred; `

// Create a Wrapper component that'll render a <section> tag with some styles
const Wrapper = styled.section` padding: 4em; background: papayawhip; height: 100vh; `

function StyledComponent() {
  return (
    <Wrapper>
      <Title>Hello World!</Title>
    </Wrapper>)}export default StyledComponent
Copy the code

Styling components

How do I bind form input to data (state)

We’ve learned how to set state in our component, but we also need a way to bind user input to that state. For example, in a login form, we might need to store the user’s username and password input in the component state. React and Vue have different ways of keeping user input and state in sync.

In Vue, we have a special instruction to do this, called v-Model. To use this, you need to create a state by using the data property, as we learned earlier. You then add the V-Model keyword to your input and specify which data variable is responsible for storing the input (this applies to form input, text areas, and selection elements).

This is a high-level, clean way to concatenate data without creating additional lambda functions or handlers.

<template>
  <div>
    <input v-model="inputState" type="text" />
    <br />
    {{ inputState }}
    <br />
    <button @click="changeInputState()">Click to say goodbye</button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      inputState: 'Hello',}},methods: {
    changeInputState: function () {
      this.inputState = 'Goodbye'}},}</script>

<style></style>
Copy the code

Here’s a small example: We have a text input and we associate it with inputState by using the V-Model keyword. Therefore, every time the user enters text, the inputState variable automatically reflects the change.

However, there is one particular thing you need to know: V-Model implements 2-way data binding, unlike React’s 1-way binding.

This means that not only does the data change when you change the input, but that the input values change if you change the data.

To prove this, I create a button and attach it to a method. Don’t worry about event handling just yet, as we’ll see in the next section. When the button is clicked, the value of the inputState variable changes and so does the input.

I encourage you to try it out for yourself by running the code. Also, notice that the initial value of your input field is ‘Hello’– it is not initialized as an empty string or empty because we set the inputState variable to ‘Hello’.

Now let’s see in React.

import { React, useState } from 'react'

function FormInputBinding() {
  const [userInput, setUserInput] = useState('Hello')

  return (
    <div>
      <input type="text" onChange={(e)= > setUserInput(e.target.value)} />
      <button onClick={()= > setUserInput('Goodbye')}>
        Click to say goodbye
      </button>
      {userInput}
    </div>)}export default FormInputBinding
Copy the code

This topic overlaps with dealing with user events, so if you don’t understand anything, wait until you finish the next section. Here, we manually handle the onChange event and call the setUserInput function to set the state to the value of the event.

As we mentioned earlier, React uses a one-way binding model. This means that changing the state of the userInput will not affect the values we see in the text input – we will not initially see Hello in the input box. Also, when we click the button, it will update the status, but the input inside the input box will keep its value.

Processing events (user input

Let’s look at another form that more closely resembles the real case of Vue and React.

<template>
  <div>
    <input
      v-model="username"
      id="outlined-basic"
      label="Username"
      variant="outlined"
    />
    <input
      v-model="password"
      id="outlined-basic"
      type="password"
      label="Password"
      variant="outlined"
    />

    <input
      v-model="termsAccepted"
      id="outlined-basic"
      type="checkbox"
      label="Password"
      variant="outlined"
    />

    <Button variant="contained" color="primary" @click="submitForm">
      Submit
    </Button>
  </div>
</template>

<script>
export default {
  data() {
    return {
      username: ' '.password: ' '.termsAccepted: false,}},methods: {
    submitForm: function () {
      console.log(this.username, this.password, this.termsAccepted)
    },
  },
}
</script>

<style></style>
Copy the code

Vue form

As you can see, we are using the V-Model properties we just learned to connect all of our input and data properties (states). Therefore, whenever the input changes, Vue automatically updates the corresponding variable.

To see how we handle button click events, see Submit buttons. We use the V-on keyword to handle click events. @click is just an abbreviation for V-on :click.

Whenever a click event occurs, it simply calls the submitForm method. You can familiarize yourself with the list of possible events by browsing the linked documentation.

In React, we could have a form like this.

import { React, useState } from 'react'

import {
  TextField,
  Checkbox,
  FormControlLabel,
  Button,
} from '@material-ui/core'

function EventHandling() {
  let [username, setUsername] = useState(' ')
  let [password, setPassword] = useState(' ')
  let [termsAccepted, setTermsAccepted] = useState(false)

  const submitForm = () = > {
    console.log(username, password, termsAccepted)
  }

  const formContainer = {
    display: 'flex'.flexDirection: 'column'.alignItems: 'center'.gap: '20px',}return (
    <div style={formContainer}>
      <TextField
        onInput={(e)= > setUsername(e.target.value)}
        id="outlined-basic"
        label="Username"
        variant="outlined"
      />
      <TextField
        onInput={(e)= > setPassword(e.target.value)}
        id="outlined-basic"
        type="password"
        label="Password"
        variant="outlined"
      />

      <FormControlLabel
        control={
          <Checkbox
            type="checkbox"
            checked={termsAccepted}
            onChange={(e)= > setTermsAccepted(e.target.checked)}
          />
        }
        label="Accept terms and conditions"
      />

      <Button variant="contained" color="primary" onClick={()= > submitForm()}>
        Submit
      </Button>
    </div>)}export default EventHandling
Copy the code

The React form

We create our state variables for each input. We can then listen for the input event, which will be accessed in the handler. In response to these events, we call the state setter to update our state.

Conditional style design

Conditional style is the binding of a class or style to an element when a condition is true.

In Vue, it can be implemented like this.

<template>
  <div>
    <button @click="toggleApplyStyles"></button>
    <p :class="{ textStyle: stylesApplied }">
      Click the button to {{ stylesApplied ? 'unstyle' : 'style' }} me
    </p>
  </div>
</template>

<script>
export default {
  data() {
    return {
      stylesApplied: false,}},methods: {
    toggleApplyStyles: function () {
      this.stylesApplied = !this.stylesApplied
    },
  },
}
</script>

<style>
.textStyle {
  font-size: 25px;
  color: red;
  letter-spacing: 120%;
}
</style>
Copy the code

Conditional style of Vue

We create a paragraph and want to apply the textStyle class only if the values of the stylesApplied data property are true. We can do this using V-bind. The colon is short for V-bind, so :class is the same as v-bind:class.

We use the V-bind object syntax to bind classes. We pass an object to the class property. TextStyle: stylesApplied}, which means that if stylesApplied is true, the textStyle class will be applied.

This is a bit complicated at first, but it helps us avoid multiple chained if statements to determine which class will be applied, and handle style binding in a clean way: class name on the left (object key), condition on the right (object value).

In React, we have to do things more primitively.

import { React, useState } from 'react'
import './styles.css'

function ConditionalStyling() {
  let [stylesApplied, setStylesApplied] = useState(false)

  return (
    <div>
      <button onClick={()= >setStylesApplied(! stylesApplied)}>Click me</button>
      <p style={{ color: stylesApplied ? 'red' : 'green' }}>Red or Green</p>
      <p className={stylesApplied ? 'styleClass' :"'} >Red with class</p>
    </div>)}export default ConditionalStyling
Copy the code

React conditional style

Here, we use plain JavaScript to bind a style object or the class name of an element. I think this makes the code a little more complicated, and I’m not a big fan of this syntax.

Conditional rendering

Sometimes we want to render a component after doing something, such as fetching data from an API. Or we want to display an error message when there is an error and a success message when there is no error.

In this case, we use conditional rendering to change the HTML to be rendered programmatically.

In Vue, there are special instructions for this as well. We can use V-if and V-else, or even V-else, to render templates based on conditions.

<template>
  <div>
    <h2 v-if="condition1">condition1 is true</h2>
    <h2 v-else-if="condition2">condition2 is true</h2>
    <h2 v-else>all conditions are false</h2>
  </div>
</template>

<script>
export default {
  data() {
    return {
      condition1: false.condition2: false,}}}</script>

<style></style>
Copy the code

This syntax allows us to create complex conditional rendering chains without having to complicate our template code with if else statements.

Here’s one way to do the same output with React.

import React from 'react'

function ConditionalRendering() {
  const condition1 = false
  const condition2 = false

  function getMessage() {
    let message = ' '

    if (condition1) {
      message = 'condition1 is true'
    } else if (condition2) {
      message = 'condition2 is true'
    } else {
      message = 'all conditions are false'
    }

    return <h1>{message}</h1>
  }

  return <>{getMessage()}</>
}

export default ConditionalRendering
Copy the code

This is just regular JS and JSX, there is no magic here.

Render an array (list)

Now let’s look at how we render the list data. In Vue, there is the V-for keyword to do this. The syntax name in names means that the name variable will always hold the current name. As the index changes, if the index is 0, it is names[0], and so on. We can also access it by specifying the index in parentheses. The V-for instruction also requires a key.

<template>
  <div>
    <h1>Names</h1>
    <ul>
      <li v-for="(person, index) in people" :key="index">{{ person.name }}</li>
    </ul>
  </div>
</template>

<script>
export default {
  data() {
    return {
      people: [{id: 0.name: 'Yigit'}, {id: 1.name: 'Gulbike'}, {id: 2.name: 'Mete'}, {id: 3.name: 'Jason'}, {id: 4.name: 'Matt'}, {id: 5.name: 'Corey',},],}},}</script>
Copy the code

Note that we can also iterate over an object’s properties using the V-for directive. Remember, in JS, arrays are just a special subset of objects with numeric keys.

In React, we’ll use the arrays.map function to iterate over Arrays and return a JXX label for each element.

import React from 'react'

function RenderingLists() {
  const cities = [
    'Istanbul'.'München'.'Los Angeles'.'London'.'San Francisco',]return (
    <div>
      <h1>Cities</h1>
      {cities.map((city, index) => (
        <h4 key={index}>{city}</h4>
      ))}
    </div>)}export default RenderingLists
Copy the code

Child to parent communication

Imagine that you have a form component and a button child within it. You want to perform some action when the button is clicked, such as calling the API to submit data — but you can’t access the form data in the button component because it’s stored in the parent component. What would you do?

Well, if you’re in a Vue, you want to issue a custom event from the child node and take action on the parent node. In React, you create a function that will be executed in the parent class (when the button is clicked) that accesses form data and passes it to the button component so it can call the parent’s function.

Let’s look at an example from Vue.

<template>
  <div>
    <button @click="buttonClicked">Submit</button>
  </div>
</template>

<script>
export default {
  methods: {
    buttonClicked: function () {
      this.$emit('buttonClicked') // Emits a buttonClicked event to parent}},}</script>

<style></style>
Copy the code

Child.vue

In our child component, we have a button that emits a buttonClicked event when clicked. We can also send data in this call. For example, if this is a text entry field instead of a button and has its own data, we can use emit to send the data to the parent component.

In the parent component, we need to listen for the custom buttonClicked event we just created.

<template>
  <form action="#">
    <input v-model="username" type="text" />
    <child @buttonClicked="handleButtonClicked" />
  </form>
</template>

<script>
import Child from './Child.vue'

export default {
  components: { Child },
  data() {
    return {
      username: ' ',}},methods: {
    handleButtonClicked: function () {
      console.log(this.username)
    },
  },
}
</script>

<style></style>
Copy the code

Parent.vue

We simply added an @ButtonClicked event to our child component call to handle the custom event.

In React, we can achieve the same result by passing a handler function to a child component. The concept was a bit complicated for me at first, but the syntax is simpler than the Vue example, and there’s no magic involved.

import React from 'react'

function Child({ handleButtonClicked }) {
  return (
    <div>
      <button onClick={()= > handleButtonClicked()}>Submit</button>
    </div>)}export default Child
Copy the code

Child.js

We access the handleButtonClicked prop and call it when the button is clicked.

import { React, useState } from 'react'

import Child from './Child.js'

function Parent() {
  const [username, setUsername] = useState(' ')

  const submitForm = () = > {
    console.log(username)
    // Post form data to api...
  }

  return (
    <div>
      <input onChange={(e)= > setUsername(e.target.value)} type="text" />
      <Child handleButtonClicked={submitForm} />
    </div>)}export default Parent
Copy the code

In the parent class, we pass the submitForm function as the handleButtonClicked prop, which does the job.

React to data/state changes

In some cases, we need to react to changes in data. For example, when you want to perform asynchronous or expensive operations in response to changes in data.

In Vue, we have the Watch property or observer. If you’re familiar with useEffect in React, this is the closest thing you’ll find in Vue, and they’re used in much the same way.

Let’s look at an example.

<template>
  <div>
    <input v-model="number1" type="number" name="number 1" />
    <input v-model="number2" type="number" name="number 2" />
    {{ sum }}
  </div>
</template>

<script>
export default {
  data() {
    return {
      number1: 0.number2: 0.sum: 0,}},watch: {
    number1: function (val) {
      this.sum = parseInt(val) + parseInt(this.number2)
    },
    number2: function (val) {
      this.sum = parseInt(this.number1) + parseInt(val)
    },
  },
}
</script>

<style></style>
Copy the code

In this case, we define number1 and number2 in our data properties. We have two separate inputs, and we want to print the sum of the numbers, and we want the sum to be updated when either input changes.

In the Watch property, we write down the name of the variable we want to observe. In this case, we want to look at both number1 and number2. If the user enters an input, the V-Model will change the corresponding data variable, and when this happens, the observation function for that variable will be fired and the value of sum will be recalculated.

Note that in a real application, you don’t need to use watch for this simple thing, you just need to put sum in computed. This is a trumped-up example of how watch works.

I recommend reading this article before using Watch for more complex things like objects, arrays, and nested structures, because you may need to learn watch options like deep and immediate.

In React, we use the built-in useEffect hook to observe changes.

import { React, useState, useEffect } from 'react'

function ReactToDataChanges() {
  const [number1, setNumber1] = useState(0)
  const [number2, setNumber2] = useState(0)
  const [sum, setSum] = useState(0)

  useEffect(() = > {
    console.log('I am here! ')
    setSum(parseInt(number1) + parseInt(number2))
  }, [number1, number2])

  return (
    <div>
      <input
        onChange={(e)= > setNumber1(e.target.value)}
        type="number"
        name="number 1"
      />
      <input
        onChange={(e)= > setNumber2(e.target.value)}
        type="number"
        name="number 2"
      />
      {sum}
    </div>)}export default ReactToDataChanges
Copy the code

UseEffect wants to run a function as the first argument when a dependency changes, and a list of dependencies as the second argument.

Remember, this is also a contrived example to demonstrate the useEffect (we can achieve the same effect without the useEffect by taking the sum variable out of the state).

I want to show you a very common use case for this hook: getting data from the API after a component loads.

useEffect(() = > {
    fetchUserData()
}, [])

const fetchUserData = async() = > {const url = ' ';
    const response = await axios.get(url);
    const user = response.data;
    setUser(user);
}
Copy the code

We can specify an empty array and run useEffect once during component rendering. In Vue, we do the same in a lifecycle hook, such as Created or Mounted.

Compute attributes vs useMemo

Vue has a concept called calculation properties, which cache fairly complex calculations and reevaluate them when a dependency changes (similar to Watch).

It was also useful in keeping our templates clean and concise by moving the logic to JavaScript. In this case, they’re just like normal variables, and we don’t want them to be a state.

<template>
  <div>
    <h3>Yigit's Favorite Cities are:</h3>
    <p v-for="city in favCities" :key="city">{{ city }}</p>
    <h3>Yigit's Favorite Cities in US are:</h3>
    <p v-for="town in favCitiesInUS" :key="town">{{ town }}</p>
    <button @click="addBostonToFavCities">
      Why is Boston not in there? Click to add
    </button>
  </div>
</template>

<script>
export default {
  computed: {
    favCitiesInUS: function () {
      return this.favCities.filter((city) = > this.usCities.includes(city))
    },
  },
  data() {
    return {
      favCities: [
        'Istanbul'.'München'.'Los Angeles'.'Rome'.'Florence'.'London'.'San Francisco',].usCities: [
        'New York'.'Los Angeles'.'Chicago'.'Houston'.'Phoenix'.'Arizona'.'San Francisco'.'Boston',].}},methods: {
    addBostonToFavCities() {
      if (this.favCities.includes('Boston')) return
      
      this.favCities.push('Boston')}}},</script>

<style></style>
Copy the code

Examples of calculations

At this point, we don’t want to put the favCitiesInUS function in our template because it is too logical.

Think of it as a function, and the output will be cached. This function is reevaluated only when favCities or usCities (their dependencies) change. To try this out, you can click the button to see how the template changes. Remember that the evaluation function does not take any arguments.

We can use the useMemo hook to achieve the same result as in React. We wrap the function in a useMemo hook and provide a list of dependencies in the second argument. Whenever one of these dependencies changes, React runs the function again.

import { React, useMemo, useState } from 'react'

function UseMemoTest(a) {
  const [favCities, setFavCities] = useState([
      'Istanbul'.'München'.'Los Angeles'.'Rome'.'Florence'.'London'.'San Francisco',
    ]),
    [usCities, setUsCities] = useState([
      'New York'.'Los Angeles'.'Chicago'.'Houston'.'Phoenix'.'Arizona'.'San Francisco'.'Boston',]),const favCitiesInUs = useMemo(() => {
    return favCities.filter((city) => usCities.includes(city))
  }, [favCities, usCities])

  return (
    <div>
      <h3>Yigit's Favorite Cities are: {favCities.map((city) => ( 

{city}

))}

Yigit'

s Favorite Cities in US are:</h3> {favCitiesInUs.map((town) => ( <p key={town}>{town}</p> ))} <button onClick={() => setFavCities([...favCities, 'Boston'])}> Click me to add </button> </div> ) } export default UseMemoTest Copy the code

Vue slots with Render Props

We sometimes want to create generic components that can display other components, such as a grid component that can display any type of project.

For this purpose, Vue has a mechanism called a slot. The logic behind slots is really simple: you open a slot in a component, and it should receive another component to render (we call it a consumer because it consumes the supplied elements).

In the producer, you pass in components that the consumer should render to its tag — you can think of them as filling slots that you open in the consumer. The first element will be rendered in the first slot, the second in the second slot, and so on.

If there is more than one slot, you must also set the name. Let’s look at an example.

<template>
  <div>
    <h3>Component in slot 1:</h3>
    <slot name="slot1"></slot>
    <h3>Hello slot1</h3>
    <slot name="slot2"></slot>
    <h3>Component in slot 3:</h3>
    <slot name="slot3"></slot>
  </div>
</template>

<script>
export default {}
</script>

<style></style>
Copy the code

Consumer.vue

Here is our consumer component. It may be creating a layout or some combination from multiple components. We create slots and give them different names.

<template>
  <div>
    <consumer>
      <custom-button
        text="I am a button in slot 1"
        slot="slot1"
      ></custom-button>
      <h1 slot="slot2">I am in slot 2, yayyy</h1>
      <custom-button text="I am in slot 3" slot="slot3"></custom-button>
    </consumer>
  </div>
</template>

<script>
import CustomButton from './CustomButton.vue'
import Consumer from './Consumer.vue'

export default {
  components: {
    CustomButton,
    Consumer,
  },
}
</script>

<style></style>
Copy the code

Producer.vue

Here is the slot where the producer passes the component to the consumer by specifying the slot name as an attribute.

If you are interested in this, here is the simple CustomButton component.

<template>
  <button>{{ text }}</button>
</template>

<script>
export default {
  props: {
    text: {
      type: String.default: 'I am a button component',,}}}</script>

<style></style>
Copy the code

Can you guess the output without running the code? This may be a good exercise to make sure you understand the slot.

In React, this is much easier. I think groove is making things too complicated. Since React uses JSX, we can pass the component to render directly as an item.

import React from 'react'
import Child from './Child'

function Parent() {
  const compToBeRendered = (
    <div>
      <h1>Hello</h1>
      <button>Im button</button>
    </div>
  )

  return (
    <div>
      <Child compToBeRendered={compToBeRendered}></Child>
    </div>)}export default Parent
Copy the code

Parent.js

import React from 'react'

function Child({ compToBeRendered }) {
  return (
    <div>
      <h1>In child:</h1>
      {compToBeRendered}
    </div>)}export default Child
Copy the code

Child.js

Final thoughts

In the last section of this article, I would like to share two thoughts about these frameworks.

As we’ve seen through the article, Vue usually has its own way of doing things and has a different construct for most things. In my opinion, that sometimes makes it a little difficult to learn.

React, on the other hand, is like pure JS, incorporating JSX: there isn’t a lot of magic, and there aren’t a lot of special keywords to learn.

While it may not be the best framework for beginners, I believe the abstractions/keywords provided by Vue (such as the V-for, V-if, and Options apis) allow you to write code at a higher level of abstraction (think adding a simple statement to iterate over components rather than a low-level multi-line map function).

These features also make your Vue code more structured and concise, because the framework is self-governing. So it has its own way of doing things, and if you do things that way, you end up with code that’s easy to read and understand.

React, on the other hand, doesn’t have a very opinionated view of things and gives developers a lot of freedom to decide the structure of their projects.

But this freedom comes at a cost: if you’re a beginner without understanding best practices, it’s easy to end up with messy code and poorly structured projects.

Another important difference, in my opinion, is that if you’re building a non-basic project with React, you’ll need to use a lot of external libraries to develop at a normal pace, which means you’ll also need to learn how these things work.

conclusion

Thank you for reading, I hope this comparison is useful. If you’d like to connect, ask questions or discuss further, feel free to leave me a comment on LinkedIn.


Yi ğ it Kemal Erinc

I am a master’s student at The Technical University of Munich and a part-time SWE at Visa. I love working on Java microservices and the front end. Please feel free to contact me 🙂


If you are reading this, please tweet the author to show your concern. thanks

FreeCodeCamp’s open source courses have helped over 40,000 people land developer jobs. Let’s start