Learning idea #1: Help junior engineers learn programming

Prerequisite for this post: You will need to know some React to understand this post.

If you have read The Key to Learning Deeply in Programming, my friend and I start to wonder: Is there any way AI can uplift the stress of building side projects and help junior engineers learn better?

Today, I spent some time breaking down problems and ideating potential solutions, and I want to use React statement management as an example to demonstrate how might we learn deeply through AI.

Break down all challenges I encounter when building my side projects.

How might we help first-time React learners to learn better?

I ask AI to generate some important concepts to learn for a React beginner and choose state & props as an example to dive deeper. This is the thread of conversation I have with AI. Feel free to skip or just read the highlight because it’s quite long.

  • Explain in simple terms: props & state
  • Demo code for explanation
  • Q: Applying in a novel scenario
  • A: Applying in a novel scenario
  • A: Explain the novel scenario
  • A: Explain the novel scenario with visualization
  • Problem context and design philosophy

Explain in simple terms

AI, can you explain props and state for me?

  1. Props: This is information that a parent component passes down to its child components. Think of it like a teacher giving books to their students. Each student gets a book (props) from the teacher (parent component). They can read, use, and learn from it, but they cannot alter the content of the book.
  2. State: This is information that a component maintains and can change over time. It’s like a note you write to yourself that you can add to, erase, and modify as you need. In terms of components, this is data that can change after the component is loaded.

Demo code for explanation

AI, generate a code example to explain.

Example 1: props

Here, we’ll create a Greeting component that receives a name via props and displays a greeting message.

function Greeting(props) {

return <h1>Hello, {props.name}!</h1>;

}

function App() {

return <Greeting name="Alice" />;

}

In this example:

  • The Greeting component accepts props.
  • props.name is used to dynamically display the name.
  • In App, we use the Greeting component and pass a name prop with the value "Alice".

Example 2: Using State

Now, let’s create a Counter component that uses state to keep track of a count value.

import React, { useState } from 'react';
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>Click me</button>
</div>
);
}

function App() {
return <Counter />;
}

In this example:

  • The Counter component uses the useState hook to create a count state variable.
  • count stores the current count, and setCount is the function to update it.
  • When the button is clicked, setCount is called to increment the count.
  • The Counter component keeps track of and displays its own count state.

Example 3: Combining Props and State

Finally, let’s combine both concepts in a more interactive example.

function User(props) {
const [loggedIn, setLoggedIn] = useState(false);
return (
<div>
<p>Welcome, {props.name}! {loggedIn ? "You are logged in." : "You are not logged in."}</p>
<button onClick={() => setLoggedIn(!loggedIn)}>
{loggedIn ? "Log out" : "Log in"}
</button>
</div>
);
}
function App() {
return <User name="Bob" />;
}

How do you feel about the response? I think this is not enough to learn the core idea of state and props. However, this is also the same thing I got when I was learning through YouTube.

Q: Applying in a novel scenario

AI, give me a novel scenario to practice this concept.

Let’s say you want to develop a simple weather application using React that displays the current weather conditions of a city. The application should have two components:

  1. CityInput: A form input field that allows users to type in the name of the city. This will be a "controlled component", meaning that the input value should be controlled by the component's state.
  2. WeatherDisplay: A component that takes the city name as a prop and displays the current weather condition of the city. Note: We'll not tackle the actual weather data fetching here, you might use an external API for that in an actual application.

How would you structure your components in terms of state and props? Could you write a simple skeleton of these components?

Hint: What information changes over time? Where does information flow?

Remember, the key thing here is to think about the state (what changes over time) and the props (how the information flows from parent to child).

It becomes interesting, right? So I responded:
- What information changes over time? weather
- How the information flows from parent to child: parent — city, children — city weather

A: Applying in a novel scenario

That’s correct!

In this scenario, the weather and the city, can change over time so they should be kept in state. The city’s state would be in CityInput, whereas WeatherDisplay's state would be the weather.

The information flow from the parent to child would be the selected city that’s passed from CityInput (parent) to WeatherDisplay (child). When the city state in CityInput changes, it will trigger a re-render, passing the new city prop to WeatherDisplay.

Esther’s viz

Here’s a simple skeleton code for the two components:

import React, { useState } from "react";
// CityInput component
function CityInput( { onUpdateCity } ) {
const [city, setCity] = useState("");
const handleChange = event => {
setCity(event.target.value);
// Notify parent component about city update
onUpdateCity(event.target.value);
};
return (
<input type="text" value={city} onChange={handleChange} placeholder="Enter city name" />
);
}
// WeatherDisplay component
function WeatherDisplay( { city } ) {
const [weather, setWeather] = useState("");
// Assume we have a fetchWeather function to get weather data
// useEffect(() => {
// fetchWeather(city).then(data => setWeather(data));
// }, [city]);

return (
<h2>The current weather in {city} is {weather}</h2>
);
}
// Parent component, here just an example
// It handles city updates from CityInput
function WeatherApp() {
const [city, setCity] = useState("");

const handleUpdateCity = (updatedCity) => {
setCity(updatedCity);
};
return (
<>
<CityInput onUpdateCity={handleUpdateCity} />
<WeatherDisplay city={city} />
</>
);
}

Please note that you’d need a real API call in WeatherDisplay to fetch weather data - it's commented out because it's not the focus of the question. In CityInput, we also introduced an onUpdateCity prop which allows CityInput to notify its parent (WeatherApp) about changes. This is a key pattern in React: "lifting state up", when the state is managed by a parent component or even higher.

A: Explain the novel scenario

It starts to get into the important part of it, so I follow up: I don’t understand onUpdateCity and handleUpdateCity.

I apologize for any confusion. Let’s dive a little deeper to understand onUpdateCity and handleUpdateCity.

Here’s their purpose:

  • onUpdateCity is basically a function that's passed as a prop from the WeatherApp component to the CityInput component. When we say onUpdateCity={handleUpdateCity} inside WeatherApp, we're saying "Hey, CityInput, here's a function that you should call when the city changes."
  • Inside the CityInput component, it calls this passed function in its handleChange function. So, any time the city value changes due to a user typing in the input field, it not only updates its own state 'city' but also informs the parent component (in this case WeatherApp) about this change by calling onUpdateCity(event.target.value).
  • handleUpdateCity is that function in the WeatherApp component that gets called. When this happens, it receives the updated city and uses it to update the state of the WeatherApp component.

The reason we do this roundabout thing is because the WeatherDisplay component, which is also a child of WeatherApp, needs to know when the city changes. But CityInput and WeatherDisplay are siblings -- they don't have a direct way to communicate. So we use their common parent WeatherApp as a conduit for that communication.

Esther’s viz. In short, parent and child are connected. But the child cannot talk to each other, so they need their parent to connect them. The parent passes the city change function (handleUpdatedCity) so the city component(child 1), can change the city data. The parent now has the city data information to pass to the city temperature component(child 2) to update the temperature.

This is a common pattern in React called “lifting state up”. Instead of trying to sync states across multiple components (which gets complex and error-prone very quickly), we “lift the state up” to a common ancestor and then distribute it down as props. This keeps our state logic in one place and our components more predictable and easier to understand.

A: Explain the novel scenario with visualization

Good job! AI starts to teach me in depth, using the parent/child information! Well, but since I still don’t understand, I ask: Can you visualize who is calling who. that’s confusing.

Absolutely, we can look at the process as a model of communication between three individuals:

  1. CityInput (a child who observes and reports)
  2. WeatherApp (a parent who listens and informs)
  3. WeatherDisplay (another child who receives updates)

Let’s represent each component with these individuals and see how they interact:

  • The CityInput (the observing child) is like a child playing outdoors. When the child observes a change (e.g., it starts to rain), they run inside to tell the parent, using the method the parent has told them to (onUpdateCity).
  • WeatherApp (the parent) is the decision-maker of the house. They are listening for updates from CityInput (the observing child) via the handleUpdateCity function. Upon hearing about the rainfall, the parent then updates their knowledge (state), which in turn informs their other child - WeatherDisplay.
  • The WeatherDisplay (the child receiving updates) then takes this new information (the weather condition) that it gets from the parent as a prop and acts on it. It may respond to this update by putting on a raincoat or grabbing an umbrella.

This represents the flow of information.

Here’s it visually:

CityInput - (observes an event and tells parent) -> WeatherApp - (updates state and informs WeatherDisplay) -> WeatherDisplay

It’s two communication lanes that form a cycle:

  1. CityInput -> WeatherApp: via onUpdateCity prop (aka the parent's instruction).
  2. WeatherApp -> WeatherDisplay: via city prop (aka the parent's update to its other child).

Hope this clarifies how the communication is happening between the components!

Problem context and design philosophy

Wow! This become so clear and finally understand more about props and state instead of pretending props.name is the world! So I AI about the problem context and philosophy for this design.

In GUI applications, the state of the application and the interface needs to change often due to user interactions (clicks, keystrokes, etc), and these changes need to be accurately reflected on the screen in real-time.

In traditional, procedural programming, this can lead to difficult-to-track bugs and inefficient code, as different parts of the application may need precise knowledge about others in order to function. React’s model abstracts away this complexity through a single-direction data flow, and a diffing algorithm that efficiently updates only the parts of the interface that need changing.

  • Bidirectional data binding (the method before react): This means that if you have two pieces of data, like a textbox and a model (an object that holds data), they are linked or “bound” together. So, if you change the data in the model, the textbox will automatically show this new data. It also means if someone types into the textbox, the data in the model will be updated to reflect that.

This seems convenient, right? But imagine if you have lots of these data bindings in a complex app. If an error pops up, it becomes difficult to trace which change caused it. Plus, with multiple components manipulating the data, it can lead to unexpected results.

  • Unidirectional data flow (React’s approach): React took a different approach, called “unidirectional data flow”. Remember the LEGO analogy? With React, data moves in one direction, from top (parent component) to bottom (child component), just like building up a LEGO structure from base to top.

This means a child component can’t directly update something in a parent component. If a change is needed, it must ask the parent component to do it. This helps keep things organized and makes code easier to understand, as you always know where the change is coming from. It also reduces the likelihood of bugs because you are controlling exactly where and how changes are made.

So, while bidirectional data binding is like a busy roundabout with traffic coming from all directions, React’s unidirectional flow can be seen more like a one-way street, which can make managing complex applications much simpler and cleaner.

Kudos to you if you actually read it till here, but look! I also learn so many new things from the conversation with AI! To summarise the learning.

  1. I learn how to apply props & state through the novel scenario
  2. I learn why props & state as a design philosophy. React is designed as a unidirectional data flow to contrast with the messy bidirectional data binding approach in the old days. Hence, the parent-child relationship makes so much more sense now!

If you look back at my thread with AI, you will realize the most important parts are missing in our learning journey when we learn it for the first time ourselves.

My thread

  • Explain in simple terms
  • Demo code for explanation
  • Q: Applying in a novel scenario (missing)
  • A: Applying in a novel scenario (missing)
  • A: Explain the novel scenario (missing)
  • A: Explain the novel scenario with visualization (missing)
  • Problem context and design philosophy (missing)

That’s why I always feel like I’m just sort of know state management but not really. However, after going through the in-depth application and problem context, it makes so much sense now. so here is the idea:

How might we assist junior engineers in learning a new concept through in-depth concept application, solidifying with problem context and design philosophy?

So far, it seems that the chat interface is bad, and it requires us to prompt it. But is there a way to integrate it with learners’ lives so beginners can pay attention to important but new learning concepts?

Me and my friend will be ideating on this tomorrow.

--

--