Day02-React基础2

一、useState的使用

1. 基础使用

useState是一个React Hook(函数),它允许我们向组件添加一个状态变量,从而控制影响组件的渲染结果。

状态变量一旦发生变化组件的视图UI也会跟着变化(数据驱动视图

const [count, setCount] = useState(0);

  1. useState是一个函数,返回值是一个数组;
  2. 数组中第一个参数是状态变量,第二个参数是set函数用来修改状态变量;
  3. useState的参数将作为状态变量的初始值;

setCount(count+1);

作用:

  1. 用传入的新值修改count
  2. 重新使用新的count渲染UI;

2. 修改状态的规则

状态不可变:在React中,状态被认为是只读的,我们应该始终替换它而不是修改它,直接修改状态不能引发视图更新。

修改对象状态:

const [form, setForm] = useState({
  name: 'jack',
})
const handleChangeName = () => {
  // form.name = 'john'
  setForm({
    ...form,
    name: 'john',
  })
}

二、组件的基础样式处理

React组件基础的样式控制有两种方式:

  1. 行内样式

    <div style={{ color: 'red' }}>this is div</div>

  2. class类名控制

    .foo {
      color: red;
    }
    <span className="foo">this is span</span>
    

三、React表单控制

1. 受控绑定

使用React组件的状态(useState)控制表单的状态。
在这里插入图片描述

function App() {
  const [value, setValue] = useState('');
  return (
    <input 
      type="text"
      value={value} {/*通过value属性绑定react状态*/}
      // 绑定onChange事件 通过事件参数e拿到输入框最新的值,
      // 反向修改到react状态
      onChange={e => setValue(e.target.value)}
    />
  )
}

2. 非受控绑定

通过获取DOM的方式获取表单的输入数据。

function App() {
  // 1. useRef生成ref对象,绑定到DOM上
  const inputRef = useRef(null);
  
  const onChange = () => {
    // 2. DOM可用时(即DOM渲染完毕后),使用ref.current获取DOM
    console.log(inputRef.current.value);
  }
  
  return (
    <input
      type="text"
      ref={inputRef}
      onChange={onChange}
    />
  )
}

四、React组件通信

组件通信就是组件之间的数据传递,根据组件嵌套关系的不同,有不同的通信手段和方法。

1. 父子通信-父传子

1.1 基础实现

实现步骤:

  1. 父组件传递数据 - 在子组件标签上绑定属性
  2. 子组件接收数据 - 子组件通过props参数接收数据
function Son(props) {
  return <div>{ props.name }</div>
}

function App() {
  const name = 'this is app name'
  return (
    <div>
      <Son name={name} />
    </div>
  )
}
1.2 props的使用

props可以传递任意的合法数据,如数字、字符串、布尔值、数组、对象、函数、JSX。

props是只读对象,子组件只能读取props中的数据,不能直接进行修改,父组件的数据只能由父组件修改。

当我们把内容嵌套在组件的标签内部时,组件会自动在名为children的prop属性中接收该内容。

<Son>
  <span>this is son</span>
</Son>

// Son组件的props上会有children属性
// props:
//    children: <span />

2. 父子通信-子传父

核心思路:在子组件中调用父组件中的函数并传递参数

function Son({ onGetMsg }){
  const sonMsg = 'this is son msg';
  return (
  	<div>
      {/* 在子组件中执行父组件传递过来的函数 */}
      <button onClick={() => onGetMsg(sonMsg)}>send</button>
    </div>
  )
}

function App() {
  const [msg, setMsg] = useState('');
  const getMsg = (msg) => {
    setMsg(msg);
    console.log(msg);
  }
  return (
    <div>
      {/* 传递父组件中的函数到子组件 */}
      <Son onGetMsg={ getMsg }/>
      {msg} 
    </div>
  )
}

3. 兄弟组件通信

实现思路:借助状态提升机制,通过共同的父组件进行兄弟之间的数据传递。

  1. A组件先通过子传父的方式把数据传递给父组件App
  2. App拿到数据之后通过父传子的方式再传递给B组件
// 1.通过子传父 A -> App
// 2.通过父传子 App -> B
function A({onGetAName}) {
  // A组件中的数据
  const name = 'this is A name'
  return (
    <div>
      this is A component,
      <button onClick={() => onGetAName(name)}>send</button>
    </div>
  )
}

function B({name}) {
  return (
    <div>
      this is B component,
      {name}
    </div>
  )
}

function App() {
  const [name, setName] = useState('');
  const getAName = (name) => {
    setName(name);
  }
  
  return (
    <div>
      <A onGetAName={getAName} />
      <B name={name} />
    </div>
  )
}

4. 跨层组件通信

步骤:

  1. 使用createContext方法创建一个上下文对象Ctx
  2. 在顶层组件(App)中通过Ctx.Provider组件提供数据
  3. 在底层组件(B)中通过useContext钩子函数获取消费数据
// App -> A -> B
import { createContext, useContext } from "react";

// 1.使用createContext方法创建一个上下文对象
const MsgContext = createContext();

function A() {
  return (
    <div>
      this is A component
      <B />
    </div>
  )
}

function B() {
  // 3.在底层组件中通过useContext钩子函数使用数据
  const msg = useContext(MsgContext);
  return (
    <div>
      this is B component, {msg}
    </div>
  )
}

function App() {
  const msg = 'this is app msg';
  return (
    <div>
      {/* 2.在顶层组件中通过Provider组件提供数据 */}
      <MsgContext.Provider value={msg}>
        this is App
        <A />
      </MsgContext.Provider>
    </div>
  )
}
export default App;

五、React副作用管理-useEffect

useEffect是一个React Hook函数,用于在React组件中创建不是由事件引起而是由渲染本身引起的操作(副作用),如发送ajax请求,更改DOM等。

useEffect(
	() => {}, // 第一个参数是一个函数,在函数内部放置要执行的操作
  []        // 第二个参数是一个数组(可选参),在数组中放置依赖项
)

1. 依赖说明

依赖项副作用函数的执行时机
没有依赖项组件初始渲染 + 组件更新时执行
空数组依赖只在初始渲染时执行一次
添加特定依赖项组件初始渲染 + 依赖项变化时执行

2. 清除副作用

在useEffect中编写的由渲染本身引起的对接组件外部的操作,如定时器,想在组件卸载时清除定时器,这个过程就是清理副作用。

useEffect(() => {
  // 实现副作用操作逻辑
  return () => {
    // 清除副作用逻辑
  }
})

六、自定义Hook实现

自定义Hook是以use开头的函数,通过自定义Hook函数可以用来实现逻辑的封装和复用。

1. 通用思路

  1. 声明一个以use开头的函数
  2. 在函数体内封装可复用的逻辑
  3. 在组件中用到的状态或者回调return出去(以对象或数组)
  4. 在哪个组件中要用到这个逻辑,就执行这个函数,解构出来状态和回调进行使用
function useToggle() {
  // 可复用的逻辑代码
  const [value, setValue] = useState(true);
  const toggle = () => setValue(!value);
  
  // 哪些状态和回调函数需要在其他组件中使用 return
  return {
    value,
    toggle
  }
}

function App() {
  const { value, toggle } = useToggle();
  
  return (
    <div>
      {value && <div>this is div</div>}
      <button onClick={toggle}>toggle</button>
    </div>
  )
}

2. 使用规则

  • 只能在组件中或者其他自定义Hook函数中调用
  • 只能在组件的顶层调用,不能嵌套在if、for、其它的函数中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值