0%

ReactJS and VueJS are definitely two of the most dominant UI frameworks for web frontend development today. Though evolving from different design patterns and concepts, the two actually share many common solutions that you might think, addressing issues that web developers will face in day-to-day work: data flow, DOM changes, component etc.

Starting from 16.8, ReactJS introduced a series of new API in a functional programing fashion called React Hooks, which allows developer to turn their class-based components into functions. On the other hand, VueJS is working on similar proposal called Composition API in upcoming major release 3.x. By taking a first glance, this move will make the transition between the two frameworks even easier than before.

However, as a majority of projects in VueJS are still in 2.x code base, here we will continue a series of articles to explain how to achieve some of the most widely used scenarios and use cases by resorting above two different approaches: VueJS class component and React Hooks functions.

Part 1: Access DOM

Part 2: Access parent context

Part 3: Props Validation

Part 4: Computation

Part 5: Imperative Programming

Part 6: Closure

Part 7:

Props are the key for components being reused in different places. It comprises of flags and parameters to mandate the component rendering into different results. Naturally checking of props is a must-have feature for component, especially for 3rd party UI library.

Normally we want to perform these kinds of check on props

  1. Required props are not missing

  2. Providing default values if optional props are not provided

  3. Props type is expected

Let’s go through them one by one:

Required & Optional Props

VueJS

VueJS offer a built-in mechanism for checking required props


props: {
firstName: {
required: false
},
lastName: {
required: true
}
}

So when you call this component without lastName property, VueJS will throw an error. IDE like VS Code and WebStorm will also warn you.

React

In React Hooks, things are even easier as component is just function:


function renderName({firstName, lastName}) {
if (!lastName) throw new Error('lastName required');
return (<div>{'hello' + firstName + lastName}</div>)
}

You can also use type-interfaced pre-process like Typescript to detect this even before runtime:


function renderName(firstName?:string, lastName:string) {

}

Default Values

For optional props, providing default value can be handy for writing the component so data input can be expected. Let’s say I am have an user prop with data structure like


{
firstName: '',
lastName: ''
}

So I can provide the user prop as a skeleton object representing this data structure. So instead of wring expression like


if (this.user && this.user.firstName)

We can safely to use this.user.firstName for the check.

It can be also very helpful in providing boolean type of prop. Say if the user name component has a flag called showFullName to control whether show first name or full name. If the component caller has not passed it, this flag will be undefined. Without default value, we can turn this flag into true when it is not there.

VueJS


props: {
firstName: {
default: 'John'
},
showFullName: {
default: true
}
}

An important notation is that, similar to its data property, if the default value is an object (or array and function, as they are object in Javascript world) instead of literal values, you have to use a function to return an object. This is for reactivity:


props: {
user: {
default: ()=>{firstName: '', lastName: ''}
}
}

React

As for React Hooks, you can process this in your function body in old fashion way:


function renderName({firstName, lastName}) {
firstName = firstName || 'John'
lastName = lastName || 'Doe'
}

Or just use ES6 or Typescript for more elegant approach


function renderName(firstName = 'John', lastName = 'Doe') {

}

But this can be tricky if you are using object as props to hold all the values. A detailed explanation here.

Type Validation

Checking type of prop can be achieved a variety of ways in VueJS, as some built-in type are there with additional power of customized validator functions


props: {
firstName: {
type: String
},
showFullName: {
type: Boolean
}
}

As stated above, React Hooks functional component can do this kind of type check simply in function body or via ES6/Typescript. You can also use props-type package provided by React team which is available for both class-based and functional component in React.

Conclusion

As indicated in above examples, functional programming is more intuitive than class-based component in terms of props type validation, as it is just Javascript expression without any learning curve at all. However, class-based examples are still handy as it provided default validators for most of your common needs.

In functional programming terms, an UI component is just about input and output. The input is the data being passed to the component hierarchically down and output is HTML being rendered. But as every developer knows, requirements are constantly changing, causing never-ending flow of adding new props to our component.
So let say we have nested structure like


<Main>
<UserList>
<UserListItem></UserListItem>
</UserList>
</Main>

Now in Main component, we need to add a new prop called type to control what to be displayed: first name, last name or full name. As UserListItem will govern the detail rendering of each user, we have to pass down the newly added prop through intermediate component. i.e. UserList which does not need this prop at all.


function UserListItem(props) {
return (props.type === 'first'?firstName:lastName)
}
<Main>
<UserList type={type} >
<UserListItem type={type}></UserListItem>
</UserList>
</Main>

Notice the type={type} will have to repeat again and again as long there are more components in the middle between Main and UserListItem. In large app we might have much deep nested structure then above example. Changing props and passing them all the way down is painstaking. To solve this, both React and VueJS offer ways to access parent context, immediately or not.
In React Hooks, we use useContext which is just syntax sugar for React.createContext in class-style component:

In VueJS, we have an (interestingly) same terminology called Provide/Inject options:

One common requirement from both React & VueJS is the context being provided at topmost level should be object instead of literal values.
As convenient it might looks like, we need to limit the usage of this pattern, as this might cause data flow difficult to understand and maintain. Use state management system and Redux or VueX if your app is sharing data between different components at many different components if necessary.