《the-road-to-learn-react》React 基础

341 阅读3分钟

一、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>
  );
};