一、create-react-app
通过create-react-app创建项目,零配置入门,各种工具和配置都发生在后台
npx create-react-app [项目名]
二、React 组件和DOM
// src/App.js
import React from 'react';
function App() {
return (
<div>
<h1>Hello World</h1>
</div>
);
}
const App = () => (// 也可以使用箭头函数定义,只返回信息可以去掉花括号{}和return
<div>
<h1>Hello World</h1>
</div>
);
export default App;
// src/index.js
import React from "react";
import ReactDOM from "react-dom";
import App from "./App";
ReactDOM.render(
<App />,
document.getElementById("root")
);
App 组件是一个 JavaScript 函数,一般称它为函数组件,目前不接收任何参数,返回的像HTML的代码称之为 JSX。
ReactDOM.render()将使用 JSX 替换 HTML 中的一个 DOM 节点,该方法需要传入两个参数:要渲染的组件和React 应用在何处输入你的 HTML。
三、React JSX
JSX展示变量采用花括号{},也可展示JavaScript表达式或函数;展示列表可使用数组内置的 JavaScript map 方法;
属性遵循驼峰式命名约定,基本和html属性一样,也会有特点属性,例如:class-》className、onclick-》onClick、for-》htmlFor;
事件处理函数:通过给 HTML 元素附加 JSX 处理函数来响应用户交互的方式;
const title = 'React';// 变量
function getTitle(title) {// 函数
return title;
}
const list = [// 列表
{title: 'React',objectID: 0},
{title: 'Redux',objectID: 1}
]
const handleChange = event => {
console.log(event);
};
function App() {
return (
<div>
<h1>Hello {title}</h1>
<h1>Hello {getTitle('React')}</h1>
{
list.map(function (item) {
return <div key={item.objectID}>{item.title}</div>;
})
}
<label htmlFor="search">Search: </label>
<input id="search" type="text" onChange={handleChange}/>
</div>
);
}
四、React父子组件和props
React props 是一个 JavaScript 对象,可以从props中访问到属性(变量和处理函数)
// 父组件
function App() {
const stories = [
{title: 'React',objectID: 0,url: 'https://reactjs.org/'},
{title: 'Redux',objectID: 1,url: 'https://redux.js.org/'}
]
return (
<div>
<List list={stories} />// 实例化List组件
</div>
);
}
// 子组件
const List = props =>
props.list.map(item => (
<div key={item.objectID}>
<span>
<a href={item.url}>{item.title}</a>
</span>
</div>
));
五、React State
1、useState(hook):
用于管理 state的工具函数,以一个初始 state 作为参数,返回包含两个值的数组,第一个值表示当前 state;第二个值是一个更新这个 state 的函数(state 更新函数);
function App() {
const [searchTerm, setSearchTerm] = React.useState('')// 空字符串为初始值,通过数组解构获取两个返回值
const handleChange = event => {
setSearchTerm(event.target.value);
};
return (
<div>
<input id="search" type="text" onChange={handleChange} />
<strong>{searchTerm}</strong>
</div>
);
}
2、useEffect(hook):
当添加浏览器存储变量后,为了避免在多个地方更新state但没有存储到浏览器,每次更新变量都在useEffect触发;
useEffect有两个参数(第一个参数是当state更改时触发的处理函数;第二个参数是所依赖的变量数组),当依赖的变量发生变化,则处理函数将会被执行;如果依赖数组是个空数组,那么处理函数只会被执行一次,即组件第一次渲染之后。
function App() {
const [searchTerm, setSearchTerm] = React.useState(localStorage.getItem('search') || 'React')// 利用浏览器存储作为初始值
React.useEffect(() => {
localStorage.setItem('search', searchTerm);
}, [searchTerm]);
const handleChange = event => {
setSearchTerm(event.target.value);
};
return (
<div>
<input id="search" type="text" onChange={handleChange} />
<strong>{searchTerm}</strong>
</div>
);
}
六、React 状态进阶reducers
使用新的 useReducer hook 替换 useState hook 来管理 stories state。
// storiesReducer
const storiesReducer = (state, action) => {
if (action.type === 'SET_STORIES') {// 获取数据并设置
return action.payload;
} else if (action.type === 'REMOVE_STORY') {// 删除数据
return state.filter(
story => action.payload.objectID !== story.objectID
);
} else {
throw new Error();
}
};
const App = () => {
const [stories, dispatchStories] = React.useReducer(
storiesReducer,
[]
);
const [searchTerm, setSearchTerm] = React.useState('React');
const handleSearch = event => {
setSearchTerm(event.target.value);
};
const searchedStories = stories.filter(function (story) {
return story.title.includes(searchTerm);
});
React.useEffect(() => {// 获取数据
setIsLoading(true);
getAsyncStories()
.then(result => {
dispatchStories({
type: 'SET_STORIES',
payload: result.data.stories,
});
setIsLoading(false);
})
.catch(() => setIsError(true));
}, []);
const handleRemoveStory = item => {// 删除
dispatchStories({
type: 'REMOVE_STORY',
payload: item,
});
};
return (
<div>
<Search search={searchTerm} onSearch={handleSearch} />
<List list={searchedStories} onRemoveItem={handleRemoveStory} />
</div>
);
};