React Basics

This article introduces the basics of React, such as commonly used JSX syntax, component composition, list rendering, and dynamic CSS.

React

Javascript

Web Development

JSX

CSS

Table of Contents

npx create-react-app appName Javascript Template

npx create-react-app appName --template typescript Typescript Template

1. Inline Styling CSS

In addition to using className to modify the styling of specific elements, JSX also supports inline CSS.

  • style is of object type, so it requires {{}} double braces to parse the expression. If the input is an object, only one pair of braces is needed.
  • Non-integer values for styling, such as px, em, require double quotes "".
  • CSS properties use camelCase format instead of -.

JSX inline CSS is commonly used to implement dynamic CSS. For example, in the code below, the color of the username depends on the user's group. Other techniques, such as dynamically triggering animations, can also be used (and can be paired with Styled-Component).

const UserProfile = props => {
  const user_profile_style = {
    fontSize: 20,
    color: "#000",
  }

  // ADMIN will have a red color
  if (props.group === "ADMIN") {
    user_profile_style.color = "red"
  }

  return (
    <div>
      <img
        src="IMAGE-PATH"
        style={{ width: 100, height: 100, borderRadius: 50 }}
      />
      <p style={user_profile_style}>Kageyame Tobio</p>
    </div>
  )
}

export default UserProfile

2. Conditional Render

  1. Using if-else
const App = () => {
  const [loading, setLoading] = useState(true)

  if (loading) {
    return <p>Loading...</p>
  }
  return <div>Hello!</div>
}
  1. Using the ternary operator
const App = () => {
  const [loading, setLoading] = useState(false)

  return <div>{loading ? <p>Loading</p> : <p>Hello</p>}</div>
}
  1. If only need to check whether to display certain elements, simply use &&
const App = () => {
  const [loading, setLoading] = useState(false)

  return <div>{!loading && <p>Hello</p>}</div>
}
  1. Using state and early return return null
const Notification = props => {
  if (!props.show) return null

  return (
    <div>
      <p>You received a message from {props.fromUser}</p>
    </div>
  )
}

3. React.Fragment

Used to group a series of child components to avoid adding unnecessary extra nodes, such as <div>.

const SubjectTableHeader = () => {
  return (
    <React.Fragment>
      <th>Title</th>
      <th>Rating</th>
      <th>Rank</th>
    </React.Fragment>
  )
}

Or you can directly use the shortcut <></> to replace React.Fragment.

const SubjectTableHeader = () => {
  return (
    <>
      <th>Title</th>
      <th>Rating</th>
      <th>Rank</th>
    </>
  )
}

4. Composition

4.1 Containment: Containers and children

When the content inside a component is uncertain, you can pass specific child content using <Component></Component>.

It's more like styling a container, where all the children inside follow the styling of that container. This is similar to the template level in atomic design theory.

For example, in the following Modal component, sometimes we don't know what the content inside will be, but what we do know is that all Modal contents share the same styling, such as modal boundaries, rounded corners, etc.

While CSS can also achieve shared styling, by creating this container component, we can pass props or add other content on top. Although we may not know the content inside the component, we know there will definitely be a button to return to the homepage. On the other hand, sharing styling with CSS would require writing a button component inside every div.

const ModalLayout = props => {
  return (
    <div className="modal-layout">
      {props.children}
      <button>Return</button>
    </div>
  )
}

const App = () => {
  return (
    <div>
      <ModalLayout>
        <h3>Submitted Successfully!</h3>
      </Modal>

      <ModalLayout>
        <h3>Enter your information</h3>
        <input type="email" placeholder="Enter email" />
      </Modal>
    </div>
  )
}

4.2 Custom Composed Props to Pass Components

If the styling of the container is more complex, such as involving positioning, you can use props to pass related child components to achieve component composition.

What's special about this example is that props are not only used to pass parameters but can also be used to pass components.

const SubjectItemLayout = props => {
  return (
    <div>
      <div className="subject-item-layout">
        <div className="subject-item-left">{props.left}</div>
        <div className="subject-item-right">{props.right}</div>
      </div>
      {props.children}
    </div>
  )
}

const App = () => {
  return (
    <SubjectItemLayout left={<SubjectBanner />} right={<SubjectDetail />}>
      <button>Return</button>
    </SubjectItemLayout>
  )
}

5. Default Props

Set default props to prevent the props passed into the component from being null.

import {DEFAULT_USER_AVATAR} from './constant'

const ProfileCard = (props) => {
  return (
    <div>
      <img src={props.avatar} alt="user avatar" />
      <h5>{props.username}</h5>
    </div>
  )
}

ProfileCard.defaultProps = {
  avatar: DEFAULT_USER_AVATAR;
}

export default ProfileCard

6. Type Check

Documentation Link

npm install prop-types

This only triggers warnings in the development environment. If the development environment isn't TypeScript, it can be used to check interfaces.

import PropTypes from "prop-types"

const Subject = props => {
  return (
    <div>
      <h3>Title: {props.title}</h3>
      <small>Category: {props.category}</small>
      <p>Rating: {props.rating}</p>
    </div>
  )
}

Subject.propTypes = {
  title: PropTypes.string.isRequired,
  category: PropTypes.oneOf(['ANIME', 'BOOK', 'MUSIC', 'GAME']), // Restrict prop values
  rating: PropTypes.oneOfType([PropTypes.string, PropTypes.number]), // Restrict prop types
}

export default Subject


## <span id="7">7. Mapping List</span>

> `<SubjectPreviewItem />` is a preview item component (including item name, image, etc., used to display item information).

Although you can directly write `js` expressions, extracting it as a separate component improves readability and reusability.

```js
const subjects = [
  {
    subject_id: 51,
    name: "CLANNAD",
    name_cn: "CLANNAD",
    rating: 9.3,
  },
  // other elements....
]
const SubjectList = props => {
  const subjects = props.subjects
  const subjectList = subjects.map(elem => (
    <SubjectPreviewItem key={elem.id} subject={elem} />
  ))

  return <div>{subjectList}</div>
}

const App = () => {
  return (
    <>
      <h1>All Subjects</h1>
      <SubjectList subjects={subjects} />
    </>
  )
}