I was never a big fan of those Top Gun frontend development platforms, such as Angular and React. Those behemoths serve as a clear illustration of how the Big Tech (a.k.a., an eight hundred-pound gorilla) can throw their weight around and, in the process, force small and medium players to paint themselves into a corner and shoot themselves in the foot. Examples that corroborate this thesis abound, and today I won’t waste anyone’s time dwelling on those depressing stories.
I want to now shift gears and admit that despite my strong disdain for those giant solutions in search of a problem, I caved and succumbed to the temptation to start creating a React training course. Seeing how popular and entrenched this behemoth tech seems to be in large organizations, I thought to myself, “Hey, let’s see if we could make some money off of that gravy train.”
However, this time, instead of starting from scratch, I decided to cheat and to use generative AI to help me create the React training course. I chose Google’s AI Studio for the task (model Gemini 2.0 Flash).
Things were going swimmingly, and Gemini 2.0 Flash was really great. It prepared a very nice, comprehensive course curriculum and peppered it with interesting and legible code examples. But it was at one point, toward the end of the course, where things started getting really interesting for me. Instead of retelling what happened, I thought it would be better if I shared here the intimate conversation Generative AI and myself had.
It all started when I interrupted Gemini 2.0 Flash to ask it to elaborate a bit on the differences between props and method parameters or function arguments. Here is how the dialog unfolded:
Me: Can you remind me about the props? How are they different from parameters or from function arguments?
Gemini 2.0 Flash: You got it! Let's clarify the relationship between props, parameters, and function arguments in the context of React components. It's a common area of confusion.
1. Function Arguments/Parameters:
Definition: Function arguments (or parameters) are values that you pass into a function when you call it. They are the inputs that the function uses to perform its task.
Example (JavaScript):
function add(a, b) { // a and b are parameters
return a + b;
}
const sum = add(5, 3); // 5 and 3 are arguments
console.log(sum); // Output: 8
Relevance to React: React components are often defined as JavaScript functions. Therefore, they can accept arguments just like any other function.
2. React Props:
Definition: Props (short for "properties") are a mechanism for passing data from a parent component to a child component in React. They are essentially arguments that are passed to a React component when it's rendered.
Purpose: Props allow you to customize and configure components, making them reusable and dynamic.
Key Characteristics:
Passed Down: Props are always passed down from a parent component to a child component.
Read-Only (from the child's perspective): A child component should not directly modify the props it receives. This helps maintain a predictable data flow.
Configuration: Props are typically used to configure how a component looks or behaves.
Example (React):
function MyComponent(props) { // props is the parameter
return (
<div>
<h1>{props.title}</h1> {/* Accessing the prop */}
<p>{props.content}</p> {/* Accessing the prop */}
</div>
);
}
function App() {
return (
<MyComponent title="Hello" content="This is the content." />
// title="Hello" and content="This is the content." are the "arguments" for the MyComponent
// that will be passed in to the props object of the MyComponent function
);
}
3. How Props Relate to Function Arguments:
Props are Function Arguments: In the simplest terms, props are the arguments passed to a React component function (or the argument to the render method in a class component, which is now less common). The React framework takes care of collecting all the attributes you specify when using a component (e.g., <MyComponent title="Hello" />) and packages them into a single object, which is then passed as the first (and often only) argument to your component function.
The props Object: Inside your component, you access these "arguments" through the props object. The attributes you specify when using the component become properties of the props object.
Destructuring (for clarity): As we've seen, it's common to use destructuring to extract specific props from the props object directly in the function signature:
function MyComponent({ title, content }) { // Destructuring props
return (
<div>
<h1>{title}</h1>
<p>{content}</p>
</div>
);
}
This is just a more concise way of writing:
function MyComponent(props) {
const { title, content } = props;
return (
<div>
<h1>{title}</h1>
<p>{content}</p>
</div>
);
}
Analogy:
Imagine a factory that produces toy cars.
Function: The factory is like a function.
Arguments: The raw materials (metal, plastic, paint) that are fed into the factory are like arguments to a regular function.
Props: Props are like the specifications or instructions that are given to the factory about how to build the car (e.g., "Make it red," "Add racing stripes," "Use a V6 engine"). The factory (the component) uses these instructions (props) to customize the final product.
Key Takeaways:
Props are the mechanism for passing data and configuration from parent components to child components in React.
Props are essentially the arguments that are passed to a React component function.
Inside the component, you access these arguments through the props object (or by destructuring the props object).
Props are read-only from the child's perspective.
I hope this explanation clarifies the relationship between props, parameters, and function arguments! Do you have any other questions?
Me: Thank you. That sounds like an interesting slant of functional programming, where a function is interchangeable with the value it returns. Am I off base here?
Gemini 2.0 Flash: That's another insightful observation! You're picking up on some deep connections here. While React props aren't exactly interchangeable with the value a function returns in the purest functional programming sense, there's a definitely a related conceptual parallel.
Let's break it down:
1. Functional Programming and Pure Functions:
In pure functional programming:
A function should always return the same output for the same input (no side effects).
A function should not modify any external state.
This makes functions predictable and easily testable.
Functions can, in many ways, be treated as expressions that are "replaced" with their resulting values. This is the essence of referential transparency.
2. React Components and Data Flow:
React components, ideally, should also strive to be as "pure" as possible (though it's not always strictly enforced, and useEffect acknowledges the need for side effects).
The UI is conceptually a function of the component's state and props: UI = f(state, props). Given the same state and props, the component should render the same UI.
Props as Input, UI as Output: Props can be seen as the "input" to the component, and the rendered UI (the JSX) can be seen as the "output" or the "value" that the component "returns".
Unidirectional Data Flow: The flow of data in React is unidirectional (data flows down from parent to child via props). This helps make the application's behavior more predictable.
3. The Connection (and the Nuances):
Props Influence the "Value": The props you pass to a component directly influence the UI that the component renders. In that sense, the props are directly related to the component's "value" (its rendered output).
Not Direct Replacement: However, it's not a direct replacement in the same way that a pure function's result can be substituted for the function call itself.
Components have internal state that also influences their output.
Components can have side effects (though useEffect is meant to manage them).
The component itself is not literally "replaced" by its rendered output in the code.
Analogy:
Think of a mathematical function:
y = f(x)
x is like the props.
y is like the UI that the component renders.
f is like the component function itself.
The value of x directly determines the value of y. But the function f remains as a separate entity.
Where React Deviates (Pragmatically) from Pure FP:
State: React components manage their own internal state, which can change over time. This is a departure from purely functional principles, where state is typically immutable.
Side Effects: React acknowledges the need for side effects (e.g., DOM manipulation, network requests) through useEffect. Pure functional programming tries to minimize or isolate side effects as much as possible.
Mutable Data (Sometimes): While React encourages immutability, it doesn't strictly enforce it. You can technically mutate objects and arrays in JavaScript, which can lead to unexpected behavior if not done carefully.
In Summary:
You're on the right track in seeing the connection to functional programming. React embraces some of the principles of functional programming (pure functions, unidirectional data flow) to make UIs more predictable and maintainable. Props play a key role in this by serving as the input that influences the component's output (its rendered UI).
However, React is also a pragmatic framework that makes compromises to deal with the complexities of building real-world UIs. It doesn't enforce strict purity in the same way that a purely functional language would.
Me: Interesting. Sounds a bit like a hybrid approach. I sense a bit of object-oriented paradigm permeating the stage. State and behaviour form a more 'bloated' conglomerate in contrast to the leanness of pure functions. Maybe I'm stretching things a bit here?
Gemini 2.0 Flash: You're not stretching things at all! You're hitting on a very accurate assessment of React's position in the landscape of programming paradigms. It is a hybrid approach, and the object-oriented influence is definitely there, even if it's not always explicitly stated.
Let's unpack why you're sensing that object-oriented "permeation":
1. Components as "Objects":
Encapsulation: React components encapsulate their own state, rendering logic, and behavior. This is very similar to the concept of encapsulation in object-oriented programming, where objects bundle data (attributes) and methods (functions) that operate on that data.
State as Internal Data: The state within a React component is analogous to the internal data or attributes of an object.
Methods (Event Handlers, etc.): The functions that handle events (e.g., handleClick, handleChange) or update the state within a component are analogous to methods of an object.
Instance-Based: Each time you render a component (e.g., <MyComponent />), you're essentially creating an "instance" of that component, similar to creating an instance of a class in OOP. Although these instances are virtual DOM representations and not directly class-based instances in modern React.
2. "Bloated Conglomerate" vs. Pure Functions:
State Management Overhead: You're right that managing state introduces overhead compared to the leanness of pure functions. Pure functions have no memory or internal state; they simply transform input to output. React components, with their state and lifecycle management, are more complex.
Potential for Side Effects: The ability to perform side effects (e.g., through useEffect) further adds to the complexity and potential for unexpected behavior. Pure functions, by definition, have no side effects.
Object-Oriented Inheritance (Absent in Functional Components): Class components (the older way of writing React components) allowed for inheritance, which is a core OOP concept. Functional components with hooks don't directly support inheritance, but composition achieves similar goals.
3. Hybrid Approach:
Functional Core: React encourages the use of functional components and techniques like immutability and unidirectional data flow, which are rooted in functional programming.
Object-Oriented Influences: The component model, encapsulation of state and behavior, and the concept of instances all have strong object-oriented undertones.
Pragmatism: React prioritizes building user interfaces effectively, even if it means compromising on strict adherence to either functional or object-oriented principles.
Analogy:
Think of building a house:
Pure Functional Approach: You'd have a set of pure functions that transform raw materials into building blocks. Each function would be highly specialized and predictable.
Object-Oriented Approach: You'd have classes for different types of building elements (walls, doors, windows). Each object would encapsulate its own data (dimensions, material) and behavior (open, close).
React's Approach: React is like a system that allows you to combine both approaches. You can create reusable components (like OOP objects) but also use functional principles to manage the data flow and rendering logic within those components.
The "Stretch" is Valid:
You're not stretching things at all. Recognizing the hybrid nature of React and the object-oriented influences is a sign of a deep understanding of the framework and its design choices. React is not a purely functional library, and it's helpful to understand why that is and what trade-offs were made.
I don’t know about you, but the AI’s responses I quoted above feel as if I’m discussing finer points of software engineering with a very experienced colleague who is deeply vested and quite knowledgeable about more rarefied, loftier, even philosophical concepts in the software development field. I felt that I could keep pushing and asking very deep, probing, even controversial questions that would take our conversation to a whole new level. It was obvious that Gemini 2.0 Flash model is paying attention to what I was saying, was reading between the lines and was able to synthesize very coherent insights and answers. I sincerely doubt that somewhere on the web there was that exact same conversation which the LLM has simply stolen and plagiarized. To me, this felt like a very neat illustration that this model is now indeed capable of generating new and unique content by stitching together various theories and bits and pieces of knowledge.
What I left the session with was the sensation that I really would not need a human instructor to teach me how to become a good React developer. Gemini 2.0 Flash is perfectly capable of doing not only a decent job at it, but also to exceed my wildest expectations.
The trick I believe, is in asking it to handle ever more probing questions.
With that in mind, I decided to abandon my idea to craft a React training course. If you need to learn React, just talk to AI.