Table of Contents
- Inline Styling CSS
- Conditional Render
- React.Fragment
- Composition
- Default Props
- Type Check with JSX
- Mapping List
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
- Using
if-else
const App = () => {
const [loading, setLoading] = useState(true)
if (loading) {
return <p>Loading...</p>
}
return <div>Hello!</div>
}
- Using the ternary operator
const App = () => {
const [loading, setLoading] = useState(false)
return <div>{loading ? <p>Loading</p> : <p>Hello</p>}</div>
}
- 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>
}
- 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
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} />
</>
)
}