1. Component Types
React DOM Components
React Components
DOM components refer to all HTML and SVG tags supported by React.
2. Setting Props for DOM Components Distinguishing traditional attributes is necessary because there are some differences in using React Props compared to HTML attributes. For example, some attributes like class
need to be written as className
due to conflicts with JavaScript keywords.
Error 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import image from './logo.svg' function App ( ) { return ( <div > <img src ={image} alt ="" class ='small' /> </div > ); }export default App ;
Correct Usage 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 import image from './logo.svg' function App ( ) { return ( <div > <img src ={image} alt ="" className ='small' /> </div > ); }export default App ;
Styling 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 import image from './logo.svg' function App ( ) { return ( <div > <img src ={image} alt ="" className ='small' style ={{}} // 这个外面的花括号表示JSX语法差值标记 ,内部的花括号是对象 ,即键值对的方式设置 /> </div > ); }export default App ;
Default unit for style is px 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import image from './logo.svg' function App ( ) { return ( <div > <img src ={image} alt ="" className ='small' style ={{ width: 100 , height: 100 }} /> </div > ); }export default App ;
Adding units 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 import image from './logo.svg' function App ( ) { return ( <div > <img src ={image} alt ="" className ='small' style ={{ width: '100vh ', height: '100vh ' }} /> </div > ); }export default App ;
Setting backgroundColor You can use an object to set styles
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 import image from './logo.svg' function App ( ) { const imgStyleObj = { width : 200 , height : 200 , backgroundColor : 'grey' } return ( <div > <img src ={image} alt ="" className ='small' style ={imgStyleObj} /> </div > ); }export default App ;
Spread syntax to set multiple properties Note that alt
generally needs to be set directly to avoid errors.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 import image from './logo.svg' function App ( ) { const imgData = { className : 'small' , style : { width : 200 , height : 200 , backgroundColor : 'grey' } } return ( <div > <img src ={image} alt ="" {...imgData } /> </div > ); }export default App ;
The ...imgData
syntax is not the same as traditional ES, it is a unique feature supported by JSX, handled during compilation.
3. Component Reuse 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 function Article ( ) { return ( <div > <h2 > Title 1</h2 > <p > Content 1</p > </div > ) }function App ( ) { return ( <> <Article /> <Article /> <Article /> </> ); }export default App ;
Page effect
4. Passing values with props 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 function Article (props ) { return ( <div > <h2 > {props.title}</h2 > <p > {props.content}</p > </div > ) }function App ( ) { return ( <> <Article title ="标题 1" content ="内容 1" /> <Article title ="标题 2" content ="内容 2" /> <Article title ="标题 3" content ="内容 3" /> </> ); }export default App ;
Using destructuring 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 function Article ({ title, content } ) { return ( <div > <h2 > {title}</h2 > <p > {content}</p > </div > ) }function App ( ) { return ( <> <Article title ="标题1" content ="内容1" /> <Article title ="标题2" content ="内容2" /> <Article title ="标题3" content ="内容3" /> </> ); }export default App ;
Passing Multiple Properties 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 function Article ({ title, content, active } ) { return ( <div > <h2 > {title}</h2 > <p > {content}</p > <p > 状态: {active ? '显示中' : '已隐藏'}</p > </div > ) }function App ( ) { return ( <> <Article title ="标题1" content ="内容1" active /> <Article title ="标题2" content ="内容2" /> <Article title ="标题3" content ="内容3" active /> </> ); }export default App ;
5. Expand Props usage scenarios 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 function Detail ({ content, active } ) { return ( <> <p > {content}</p > <p > 状态: {active ? '显示中' : '已隐藏'}</p > </> ) }function Article ({ title, detailData } ) { return ( <div > <h2 > {title}</h2 > <Detail {...detailData } /> </div > ) }function App ( ) { const articleData = { title : '标题1' , detailData : { content : '内容1' , active : true , } } return ( <> <Article {...articleData } /> </> ); }export default App ;
6. Passing nested content using children
Basic Usage 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 function List ({ children } ) { return ( <ul > {children} </ul > ); }function App ( ) { return ( <> <List > <li > 列表项1</li > <li > 列表项1</li > <li > 列表项1</li > </List > <List > <li > 列表项2</li > <li > 列表项2</li > <li > 列表项2</li > </List > </> ); }export default App ;
Deliver more content 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 function List ({ children, title, footer = <div>默认底部</div> } ) { return ( <> <h2 > {title}</h2 > <ul > {children} </ul > {footer} </> ); }function App ( ) { return ( <> <List title ="列表1" footer ={ <p > 这是底部内容1</p > } > <li > 内容1</li > <li > 内容2</li > <li > 内容3</li > </List > <List title ="列表2" footer ={ <p > 这是底部内容2</p > } > <li > 内容A</li > <li > 内容B</li > <li > 内容C</li > </List > <List title ="列表3" > <li > 内容X</li > <li > 内容Y</li > <li > 内容Z</li > </List > </> ); }export default App ;
Note that in the above methods, the data is passed from the parent component to the child component, and the data is read-only. The child component cannot modify the data and pass it to the parent component.
7. Child component passes value to parent component Basic Usage 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import { useState } from "react" ;function Detail ( ) { const [status, setStatus] = useState (true ) function handleClick ( ) { setStatus (!status); } return ( <div > <button onClick ={handleClick} > 按钮</button > <p style ={{ display: status ? 'block ' : 'none ' }}> Detail的内容</p > </div > ); } function App() { return ( <> <Detail /> </> ); }export default App ;
Passing a callback function 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 import { useState } from "react" ;function Detail ({ onActivate } ) { const [status, setStatus] = useState (true ) function handleClick ( ) { setStatus (!status); onActivate (!status); } return ( <div > <button onClick ={handleClick} > 按钮</button > <p style ={{ display: status ? 'block ' : 'none ' }}> Detail的内容</p > </div > ); } function App() { function handleActivate(status) { console.log(status); } return ( <> <Detail onActivate ={handleActivate} /> </> ); }export default App ;
8. Use Context to pass values to multiple components Creating a Context 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 import React , { createContext, useContext, useState } from 'react' ;const ThemeContext = createContext (null );function ThemeProvider ({ children } ) { const [theme, setTheme] = useState ('light' ); const toggleTheme = ( ) => { setTheme (prevTheme => prevTheme === 'light' ? 'dark' : 'light' ); }; return ( <ThemeContext.Provider value ={{ theme , toggleTheme }}> {children} </ThemeContext.Provider > ); }function ThemedButton ( ) { const { theme, toggleTheme } = useContext (ThemeContext ); return ( <button onClick ={toggleTheme} style ={{ backgroundColor: theme === 'light' ? '#fff ' : '#333 ', color: theme === 'light' ? '#333 ' : '#fff ', padding: '10px 20px ', border: '1px solid #ccc ', borderRadius: '4px ' }} > 当前主题: {theme} (点击切换) </button > ); }function App ( ) { return ( <ThemeProvider > <div style ={{ padding: '20px ' }}> <h1 > React Context 示例</h1 > <p > 这个示例展示了如何使用 Context 共享主题状态</p > <div style ={{ marginTop: '20px ' }}> <ThemedButton /> </div > </div > </ThemeProvider > ); }export default App ;
Deep understanding of Context The return value of createContext is an obj object, which contains Provider and Consumer.
The official code definition is as follows:
1 2 3 4 5 6 7 8 9 10 11 12 interface Context <T> extends Provider <T> { Provider : Provider <T>; Consumer : Consumer <T>; displayName?: string | undefined ; }
In the parent place, use the Provider tag.
The modern Consumer component is rarely used due to the more concise useContext
Old version 1 2 3 4 5 <ThemeContext .Consumer > {value => ( )} </ThemeContext .Consumer >
Modern Way 1 const value = useContext (ThemeContext );
Official nesting case 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 import { createContext, useContext } from 'react' ;const LevelContext = createContext (0 );export default function ProfilePage ( ) { return ( <Section > <Heading > My Profile</Heading > <Post title ="旅行者,你好!" body ="来看看我的冒险。" /> <AllPosts /> </Section > ); }function Heading ({ children } ) { const level = useContext (LevelContext ); switch (level) { case 0 : throw Error ('Heading 必须在 Section 内部!' ); case 1 : return <h1 > {children}</h1 > ; case 2 : return <h2 > {children}</h2 > ; case 3 : return <h3 > {children}</h3 > ; case 4 : return <h4 > {children}</h4 > ; case 5 : return <h5 > {children}</h5 > ; case 6 : return <h6 > {children}</h6 > ; default : throw Error ('未知的 level:' + level); } }function AllPosts ( ) { return ( <Section > <Heading > 帖子</Heading > <RecentPosts /> </Section > ); }function Section ({ children, isFancy } ) { const level = useContext (LevelContext ); return ( <section className ={ 'section ' + (isFancy ? 'fancy ' : '') }> <LevelContext.Provider value ={level + 1 }> {children} </LevelContext.Provider > </section > ); }function RecentPosts ( ) { return ( <Section > <Heading > 最近的帖子</Heading > <Post title ="里斯本的味道" body ="...那些蛋挞!" /> <Post title ="探戈节奏中的布宜诺斯艾利斯" body ="我爱它!" /> </Section > ); }function Post ({ title, body } ) { return ( <Section isFancy ={true} > <Heading > {title} </Heading > <p > <i > {body}</i > </p > </Section > ); }
Pay attention to the Section
function and Heading
function.
The Heading
tag does not pass a value, but it can automatically obtain the corresponding level because the parent component or grandparent component provides the value downward.
1 2 3 <LevelContext .Provider value={level + 1 }> {children} </LevelContext .Provider >
Child components or grandchild components use useContext(LevelContext) to obtain the value passed from the upper layer.
The summary is as follows 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 1) 创建 Context 容器对象: const MyContext = createContext(defaultValue); 2) 使用 Provider 组件传递数据: <MyContext.Provider value={providedValue}> {children} </MyContext.Provider> 3) 后代组件读取数据: // 方式一(现代方式): 仅适用于类组件 const value = useContext(MyContext); // 方式二(旧版方式): 适用于函数组件和类组件 <MyContext.Consumer> {value => ( // 使用value )} </MyContext.Consumer>