text: Is 2020 and the original Thinking in React article still has class components in it, so I feel is time to do an updated version of it:
  Start mocking
  We should always start with a mock, either provided by a designer/design team in those big projects, or made by ourselves if it's a small personal project. So let's say we want the classic login experience:
  Break mock into components
  Now that we have the mock, we need to take a look at it and identify its parts:
  Once identified, we should use clear names for every "component" (PascalCase by React convention):
  LoginForm(red): The whole login form.
  SubmitButton(green): The button to submit the "form".
  Label(pink): The form labels.
  Input(orange): The form inputs.
  PasswordInput(light blue): The form input with type password.
  Build components
  Now that we have identified the components, let's build them!
  const Label = props => <label {...props} />; const Input = props => <input {...props} />; const PasswordInput = ({ type = "password", ...props }) => ( <Input {...{ type, ...props }} /> ); const SubmitButton = ({ type = "submit", ...props }) => ( <button {...{ type, ...props }} /> ); const LoginForm = props => <form {...props} />;
  Notice, that we can even reuse
  Input inside
  PasswordInput.
  Use components
  Now that we have those components, we can use them to bring our mock to life. Let's call this wrapping component
  LoginContainer:
  const LoginContainer = () => ( <LoginForm> <Label htmlFor="username">Username</Label> <Input id="username" name="username" /> <Label htmlFor="password">Password</Label> <PasswordInput id="password" name="password" /> <SubmitButton>Login</SubmitButton> </LoginForm> );
  This needs API interaction and eventHandling, but first...
  Early optimizations
  While working on the components, we might detect optimizations such as every time we use an
  Input or
  PasswordInput component, we add a
  Label to it, so in order to keep DRY, let's create components to avoid repetition:
  const FormInput = ({ name, id = `${name}-id`, title, ...props }) => ( <> <Label htmlFor={id}>{title}</Label> <Input {...{ id, name, title, ...props }} /> </> ); const FormPasswordInput = ({ name, id = `${name}-id`, title, ...props }) => ( <> <Label htmlFor={id}>{title}</Label> <PasswordInput {...{ id, name, title, ...props }} /> </> );
  So now, our
  LoginContainer looks like this:
  const LoginContainer = () => ( <LoginForm> <FormInput name="username" title="Username" /> <FormPasswordInput name="password" title="Password" /> <SubmitButton>Login</SubmitButton> </LoginForm> );
  Adding state
  State should generally be left for last, thinking and designing everything as stateless as possible, using props and events. It makes components easier to maintain, test and overall understand.
  If you need state, it should be handled by either state containers (Redux, MobX, unistore, and so on) or a container/wrapper component. In our super simple login example, the place for the state could be
  LoginContainer itself, let's use React hooks for this:
  const LoginContainer = () => { const [username, setUsername] = useState(""); const [password, setPassword] = useState(""); const login = async event => { event.preventDefault(); const response = await fetch("/api", { method: "POST", body: JSON.stringify({ username, password, }), }); // Here we could check response.status to login or show error }; return ( <LoginForm onSubmit={login}> <FormInput name="username" title="Username" onChange={event => setUsername(event.currentTarget.value)} value={username} /> <FormPasswordInput name="password" title="Password" onChange={event => setPassword(event.currentTarget.value)} value={password} /> <SubmitButton>Login</SubmitButton> </LoginForm> ); };
  The approach of avoiding state is related to Functional Programming principles, but basically is to keep the components as pure as possible.
  TL;DR
  - Mock.
  - Identify components.
  - Build them.
  - Use them (and optimize them when needed).
  - Try to stay as stateless as possible. Add state only if needed.
  That's it! Thank you for reading!
  Discussion
  Thank you for writing! I saw some notations that I haven't used myself, so I'll have to keep those in mind. I was surprised to see the shorthand for
  <Fragment>, only to find out that it has been in React since 2017 :(
  I've been trying to into Hooks (I have some projects with classbased components that could benefit from it). So when I got to the part referencing Hooks, I was a little bummed out that the article stopped there. Maybe it would make a nice subject voor a next article.
  Sure! I can write a follow-up on how to think state and lifecycle the "2020 way". I saw several articles talking about how to move from class methods to hooks, but the idea behind hooks is doing things differently, not doing the same things with a different syntax.
  Follow me either in here or in Twitter and I'll write that article soon.
  Thanks for the inspiration, I'll mention this comment in the next post if you don't mind 😊
  You have a new follower! While you are at it, it might be interesting if you can share your thoughts on (shared) state with
  useStateand
  userReducerin comparison with Redux. As again, I have some projects on which Redux was used, but I have the feeling that the dependency on Redux could be dropped by using
  use*+
  Provider. At the same time, Redux might be the better choice for certain problems/scenarios.
  Hi and thanks for writing this article.
  Out of curiosity - why do you need different FormInput and FormPasswordInput when you can pass the input type as prop?
  Thanks
  Hi! Is just an abstraction so you can have separate behaviors/styles in those components down the line. Let's say for example that you want to add that 👁️ button some password fields have to show the password. If you had that directly in the Input then you need to add a ternary or if to show it only when type is "password", but with this approach you can have that button and all its styles encapsulated in the
  FormPasswordInputcomponent.
  Is funny how HTML has input with type to show all kinds of different elements, but for Headings they have h1, h2, h3, and so on.
  Thanks a lot for taking the time to read and comment, Yuriy!