Skip to main content

06 Intro to React

React

介绍

react是一个开源JavaScript库,其中包含很多组件(component),每个组件是一个“fake HTML tag”。组件可以在一个文件里(抽象地)实现一系列html、css、js的功能。其中各种组件以一定结构(类似树)组织在一起。

react and component

props

props 代表从亲组件到子组件中传递的信息。react可以通过亲组件决定子组件的各种属性,它是不可变的,并且不能子到亲反向传递。

props

state

state代表组件所维护的信息,它是可变的,可以根据程序设置或用户输入修改。

以post state为例,对于post(亲组件),它没有props,只有state,state存储了各条评论(子组件)。而子组件没有state只有props:评论发出后就不可修改,但评论数、评论如何修改可变。

post state

更进一步地,现在要给评论添加回复功能,注意回复有默认全部隐藏/全部显示两种状态,并且评论的内容一旦发布就不可变。那么,合理的解决方案是给评论增加state,将回复作为评论的子组件,通过state调整回复隐藏/显示。

comment replies

组件结构(component structure)

props和state共同构成了component structure。下图是前两部分的总结:

component structure

react practice

说明与相关网址

评论

练习中的评论由两部分构成:评论人和评论内容。

首先,ppt带着我们创建了一个框架:

import React, { useState } from 'react'

const CommentReply = (props) => {

// Function logic (JavaScript)

return (
// to render
)
}

export default CommentReply

import React, { useState } from 'react' 从react库中导入了React对象和useState hook(暂略)。CommentReply 定义了一个函数组件, props 作为函数参数代表组件属性, return 中的部分是需要渲染的内容。最后一行 export default CommentReply 将这个组件设置为默认导出,导出允许将函数、类等共享到另一个文件。

接下来,添加需要render的内容:

const CommentReply = (props) => {
return (
<div className="comment-text">
<h5>Joyce Yoon</h5>
<p>woww peak preschool energyy</p>
</div>
)
}

括号中的 <div> 是需要渲染的内容。但是这段代码无法复用,解决方案是将评论中的信息通过props传递(大括号允许读取组件中变量的值)。

const CommentReply = (props) => {
return (
<div className="comment-text">
<h5>{props.name}</h5>
<p>{props.content}</p>
</div>
)
}

另外,注意到在这段js代码里,出现了类似HTML的内容。这部分内容被称作JSX。kimi的说法是JSX是js的语法扩展,允许写入类似HTML的标记;而ppt将JSX称作“stricter version of HTML”。

从这个网站可以直观地看到HTML和JSX的差异:
https://transform.tools/html-to-jsx

下一步是增加state。在 return 之前添加一行:

const [isLiked, setIsLiked] = useState(false)

这句话通过 (false)isLiked 这个state初始化为false,并声明 setIsLiked 是用于更新 isLiked 状态的函数。
使用 setIsLiked(true) 等类似语句可以更改 isLiked 状态。

接下来,在 return 的部分添加

<p>{isLiked ? "Liked" : "Like"}</p>

按照相应条件渲染 isLiked (具体见w2)。

facebook

facebook的结构如下:

facebook sturcture

相关代码写在 app.js 中,可以看到facebook包含app、navbar、intro、photos、post五个部分。

import React from "react";
import NavBar from "./NavBar";
import Intro from "./Intro";
import Photos from "./Photos";
import Post from "./Post";

const App = () => {
return (
<div>
<NavBar />
<div>
<Intro />
<Photos />
</div>
<Post />
</div>
);
};

export default App;

在最开始的导入部分,首先导入了react库,然后从NavBar.js、Intro.js等文件导入各个组件。然后 return 返回一个div组件,将NavBar等包含为它的子组件,最后设置App导出。

可以看到上文中react库的两次导入使用了不同的语法:

import React from "react";
import React, { useState } from 'react'

在上面两行导入中,第一行只导入了react库,第二行额外导入了一个钩子。在JavaScript中,分号是可选的,第一行显示地使用了分号,第二行省略了。此外,通常来说,JavaScript中单引号和双引号没有区别。

下一步是由亲组件向子组件传递props。传递props的语法是,在亲组件 return 的div里写

<Post name="Kenneth" text="Welcome to web lab!" />

其中 Post 是子组件,而 nametext 以及它们的内容就是props。

const App = () => {
return (
<div>
<NavBar />
<div>
<Intro education="Massachusetts Institute of Technology (MIT)" city="Ridgefield, Connecticut" />
<Photos links={["pic1.jpg", "pic2.jpg", "pic3.jpg", "pic4.jpg", "pic5.jpg", "pic6.jpg", "pic7.jpg"]} />
</div>
<Post name="Kenneth Choi" text="Sign up for web lab!" />
</div>
);
};

现在App.js中的内容已经完成,下一步是利用props完成各个子组件的渲染。在亲组件中传递的props会出现在子组件的参数中。

Intro.js

import React from "react";

const Intro = (props) => {
return (
<div>
<p>
Studies at <b>{props.education}</b>
</p>
<p>
From <b>{props.city}</b>
</p>
</div>
)
};

export default Intro;

其中 <b> 标签表示文本加粗。

Photos.js

import React from "react";

const Photos = (props) => {
const myImageTags = props.links.map((photoLink) => {
return <img src={photoLink} />;
});

return (
<div>
<h3>Photos</h3>
{myImageTags}
</div>
)
}

export default Photos;

这段代码利用map创建了一个数组,对于每个 photoLink 返回一个img标签。JSX用花括号引入JavaScript表达式,将其渲染到了页面上。

Post.js

import React, { useState } from "react";

const Post = (props) => {
const [isLiked, setIsLiked] = useState(false);

return (
<div className="Post">
<h3>{props.name}</h3>
<p>{props.text}</p>
<button
onClick = {() => {
setIsLiked(!isLiked);
}}>
{isLiked ? "Liked" : "Like"}
</button>
</div>
);
};

export default Post;

其中 <button> 的部分会在以后的课程中提及。

显然课堂上的这些练习没有完成一个完整的项目,对这个项目的完善将写在补充部分中。

总结

这两张幻灯片可以概括这节课的内容:

react recap 1

react recap 2

补充