Logo of react
React 19Functional components
Logo of vue
Vue 3.5Composition API

Props — component’s parameters, attributes

Props are like parameters in functions. Use props to customize components.

Logo of react React 19, Functional components

React's design philosophy is "props are just function arguments."

Logo of vue Vue 3.5, Composition API

Vue requires you to explicitly declare which props your component accepts using defineProps().

Props are reactive.

Vue props are deeply immutable from the child's perspective. Children should emit events back to the parent.

Example of using props

Logo of react React 19, Functional components
interface Props {  title: string  isPublished?: boolean  publishedAt?: Date}export default function ArticleCard({  title,  isPublished,  publishedAt,}: Props) {  return (    <>      <h1>{title}{!isPublished && ' (draft)'}</h1>      {        publishedAt          ? <span>{publishedAt.toString()}</span>          : undefined      }    </>  )}

Using

<ArticleCard  title="React"  publishedAt={new Date()}  isPublished/>
Logo of vue Vue 3.5, Composition API
<script setup lang="ts">import { defineProps } from 'vue';const { title, publishedAt, isPublished } = defineProps<{  title: string;  isPublished?: boolean;  publishedAt?: Date;}>();</script><template>  <h1>{{ title }}{{ !isPublished && ' (draft)' }}</h1>  <span v-if="publishedAt">{{ publishedAt }}</span></template>

Using

<ArticleCard  title="Vue"  :publishedAt="new Date()"  isPublished/>

Default (fallback) values

Logo of react React 19, Functional components
export default function MyComponent({  greeting = 'Hello',  isAdmin = false,  user = { name: 'Guest' },}: {  greeting?: string  isAdmin?: boolean  user?: { name: string }} = {}) {  return (    <div>      <p>{greeting}</p>      <p>Admin: {isAdmin ? 'Yes' : 'No'}</p>      <p>User: {user.name}</p>    </div>  )}
Logo of vue Vue 3.5, Composition API
<script setup lang="ts">const {  greeting = 'Hello',  isAdmin = false,  user = () => ({ name: 'Guest' }),} = defineProps<{  greeting?: string;  isAdmin?: boolean;  user?: { name: string };}>();</script><template>  <div>    <p>{{ greeting }}</p>    <p>Admin: {{ isAdmin ? 'Yes' : 'No' }}</p>    <p>User: {{ user.name }}</p>  </div></template>

Boolean Casting

Logo of react React 19, Functional components
interface Props {  disabled?: boolean}

Usage

<Button disabled />          <!-- disabled = true --><Button disabled={false} />  <!-- disabled = false --><Button disabled={true} />   <!-- disabled = true --><Button />                   <!-- disabled = undefined -->
// ❌ Wrong - won't coerce<Button disabled="true" /> // (string, not boolean!)// ✅ Correct<Button disabled={true} /> // boolean
Logo of vue Vue 3.5, Composition API

Vue docs (Boolean Casting)

<script setup lang="ts">const { disabled, size } = defineProps<{  disabled?: boolean;  size: boolean | string;}>();</script>

Usage

<Button />                    <!-- disabled = false --><Button :disabled="false" />  <!-- disabled = false --><Button disabled />           <!-- disabled = true --><Button size />               <!-- size = true (casting) --><Button size="large" />       <!-- size = "large" (string) -->

The Boolean absent props will be cast to false.

An absent optional prop other than Boolean will have undefined value.

Required and Optional

Logo of react React 19, Functional components
  • Optional — by default
  • Required — add “isRequired” to the field in “propTypes”
export default function MyComponent({  start,  disabled = false,  description,}: {  start: number;  disabled?: boolean;  description?: string | null;}) {  return (...)}
Logo of vue Vue 3.5, Composition API
  • Optional — by default OR “required: false”
  • Required — add “required: true” as a prop property
const {  start,  disabled = false,  description,} = defineProps<{  start: number;  disabled?: boolean;  description?: string | null;}>();

The Boolean absent props will be cast to false.

Conditional props

This pattern prevents developers from passing invalid prop combinations.

There are used discriminated unions with TypeScript. A discriminant (usually a literal type like variant: 'text') determines which other properties are valid. You use the never type to explicitly forbid properties in certain branches.​

Logo of react React 19, Functional components
type Props =  | {      variant: 'text';      icon?: never;      label: string;    }  | {      variant: 'icon';      icon: React.ReactNode;      label?: never;    };export default function Button({ variant, label, icon }: Props) {  <button>{variant === 'text' ? label : icon}</button>;}

Usage:

// ✅ <Button variant="text" label="Click me" />// ✅ <Button variant="icon" icon={<Icon />} />// ❌ <Button variant="text" icon={<Icon />} /> // TypeScript error!// ❌ <Button variant="icon" label="Click me" /> // TypeScript error!
Logo of vue Vue 3.5, Composition API
<script setup lang="ts">type Props =  | {      variant: 'text';      icon?: never;      label: string;    }  | {      variant: 'icon';      icon: any;      label?: never;    };const { variant, label, icon } = defineProps<Props>();</script><template>  <button>    {{ variant === 'text' ? label : icon }}  </button></template>

Watch "Conditional Properties in Vue.js" on YouTube

Validation

Logo of react React 19, Functional components
type Status = 'draft' | 'published' | 'archived'interface Props {  title: string  content: string | number  status?: Status  rating?: number}const validateProps = ({ status, rating }: Props) => {  const errors: string[] = []  if (status !== undefined) {    if (!['draft', 'published', 'archived'].includes(status)) {      errors.push(        `Invalid status: "${status}".        Must be one of: draft, published, archived`      )    }  }  if (rating < 0 || rating > 5) {    errors.push(`Rating: ${rating} must be between 0 and 5`)  }  if (errors.length > 0) {    console.warn('[Props Validation]', errors.join('\n'))    if (process.env.NODE_ENV === 'development') {      throw new Error(errors.join('\n'))    }  }}export default function BlogPost({  title,  content,  status = 'published',  rating,}: Props) {  validateProps({ title, content, status, rating })  return (...)}
Logo of vue Vue 3.5, Composition API

Vue docs (Props Validation)

<script setup lang="ts">type Status = 'draft' | 'published' | 'archived';defineProps({  title: {    type: String, // Basic type check    required: true,  },  content: {    type: [String, Number], // Multiple possible types    required: true,  },  status: {    type: PropType<Status>,    default: 'published',    validator: (value: Status) => {      return ['draft', 'published', 'archived'].includes(value);    },  },  rating: {    type: Number,    validator: (value: number) => {      return value >= 0 && value <= 5;    },  },});</script>

When prop validation fails, Vue will produce a console warning (if using the development build).