react 使用hooks

设置 state

import React, { useState } from "react";
const l = console.log;

function Test() {

  const [n, setN] = useState(0);
  const [info, setInfo] = useState({
    name: "ajanuw",
  });

  function handleAddN() {
    setN(n + 1);
  }
  function handleInputChange(e) {
    setInfo({
      ...info,
      name: e.target.value,
    });
  }

  return (
    <div>
      <p>test</p>
      <p>{n}</p>
      <button onClick={handleAddN}>click me</button>
      <hr />
      <input type="text" value={info.name} onChange={handleInputChange} />
    </div>
  );
}

useEffect 钩子

它像是 componentDidMount, componentDidUpdate, and componentWillUnmount 这3个钩子
他将在第一次渲染运行,状态改变时运行,返回一个函数来做到 componentWillUnmount 里面做的一些事情
可以执行多个
第2个参数可以监听指定的数据更新才执行

import React, { useState, useEffect } from "react";
const l = console.log;
function Test() {
  const [age, setAge] = useState(0);
  const [info, setInfo] = useState({
    name: "ajanuw",
  });

  useEffect(
    () => {
      document.title = `hello ${info.name}`;
      let timer = setTimeout(() => {
        document.title = `react app`;
      }, 2000);

      return () => {
        l("卸载");
        clearTimeout(timer);
      };
    },
    [info],
  );

  useEffect(
    () => {
      l("只有age状态更新,才能执行");
    },
    [age],
  );

  function handleInputChange(e) {
    setInfo({
      ...info,
      name: e.target.value,
    });
  }

  return (
    <div>
      <input type="text" value={info.name} onChange={handleInputChange} />
    </div>
  );
}

编写自己的 hooks

就类似编写 高阶组件和渲染组件差不多

function Test() {
  const [age, setAge] = useState(0);
  const ajanuw = useInput("ajanuw");
  const suou = useInput("suou");

  useEffect(
    () => {
      l("只有age状态更新,才能执行");
    },
    [age],
  );

  return (
    <div>
      <input type="text" {...ajanuw} />
      <br />
      <input type="text" {...suou} />
    </div>
  );
}

function useInput(iv) {
  const [info, setInfo] = useState({
    name: iv,
  });

  useEffect(
    () => {
      document.title = `hello ${info.name}`;
      let timer = setTimeout(() => {
        document.title = `react app`;
      }, 2000);
      return () => {
        clearTimeout(timer);
      };
    },
    [info],
  );

  function handleInputChange(e) {
    setInfo({
      ...info,
      name: e.target.value,
    });
  }

  return {
    value: info.name,
    onChange: handleInputChange,
  };
}

useContext

获取 Context 上下文

rx

const l = console.log;

function Test(props) {
  const btnRef = useRef();
  useEffect(() => {
    const click$ = fromEvent(btnRef.current, "click");
    click$
      .pipe(
        map(v => v.type),
        throttleTime(2000),
      )
      .subscribe(l);
    return () => {
      click$.unsubscribe();
    };
  });
  return (
    <>
      <button ref={btnRef}>click me</button>
    </>
  );
}

加载异步数据 更具体的文章

useEffect 传入空数组可以避免在组件更新时激活它,但仅用于组件的安装

import React, { useState, useEffect } from "react";
import axios from "axios";
import Mock from "mockjs";

Mock.mock("/mock/a", "post", opt => {
  const body = JSON.parse(opt.body);
  return Mock.mock({
    code: body.p >= 3 ? 1 : 0,
    "data|2": [
      {
        "id|+1": 1,
        label: "@word",
      },
    ],
    // data: [],
  });
}).setup({
  timeout: 1200,
});

const l = console.log;

function Test(props) {
  const { status, list, getMore, loading, error } = useDataApi(
    0,
    [],
    "/mock/a",
  );

  return (
    <>
      {loading && <div>加载中</div>}
      {!!list.length && (
        <ul>
          <li>
            <button onClick={getMore}>加载更多</button>
          </li>
          {list.map((el, i) => (
            <li key={i}>{el.label}</li>
          ))}
        </ul>
      )}
      {error && <div>暂无数据</div>}
    </>
  );
}

function useDataApi(initStatus, initData, url) {
  const [status, setStatus] = useState(initStatus); // 0 ok, 1 notData, 2 loading
  const [p, setP] = useState(1);
  const [list, setList] = useState(initData);

  useEffect(
    () => {
      getList();
    },
    [p],
  );

  async function getList() {
    setStatus(2);
    let { code, data } = await axios.post(url, { p });
    if (code === 1) {
      setStatus(1);
    } else {
      setList(pdata => [...pdata, ...data]);
      setStatus(0);
    }
  }

  function getMore() {
    setP(pp => pp + 1);
  }

  return { status, list, getMore, loading: status === 2, error: status === 1 };
}

export default Test;
posted @ 2018-12-16 21:20  Ajanuw  阅读(587)  评论(0编辑  收藏  举报