React-hooks

Hooks

const {uerState}=React

function Counter() {
    const [count, setCount] = useState(0);// 写在外层

    return (<div>
        count:{count}
        <button onClick={_ => {
            setCount(count + 1)
        }}>加一
        </button>
        <button onClick={_ => {
            setCount(count - 1)
        }}>减一
        </button>
    </div>)
}

useState 参数是对象的时候

import {useState} from 'react'
const Greeting = () => {
    const [data, setDate] = useState({
        count: 0,
        name: 'cjg',
        age: 19
    });
    const handlerClick = () => {
        const {count} = data;
        setDate({
            ...data,
            count: count + 1
        })
    };
    return <>
        {data.count}
        <button onClick={handlerClick}>点我</button>
    </>
};

====
    const Greeting = () => {
    const [data, setDate] = useState({
        hits: [
            {name: 'zhangsan', id: 1},
            {name: 'lisi', id: 2},
            {name: 'wangwu', id: 3},
            {name: 'zhaoliu', id: 4},
        ]
    });
    return (
        <>
            {data.hits.map(value => (
                <div key={value.id}>{value.name}</div>
            ))}
        </>
    )
};

Hooks使用规则

只能在函数的最外层调用hook

只能在React的函数组件中调用Hooks

属于纯命令API

import {useEffect} from 'react'

//类似于componentDidMount 和componentDidUpdate,做DOM的更改操作
    useEffect(()=>{
        //更新文件信息
        document.title = ` ${count} times`;
    })

出现多次调用的副作用(下面这样写,很有必要)

useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]); // 只有当count的值发生变化时,才会重新执行`document.title`这一句

  useEffect(() => {
        console.log('compoentDidMount or componentDidUpdate');//更新后
        return () => {
            console.log('componentWillUnmout');// 更新前
        }
    }, [name]);
不让他造成副作用,但是没有目标就写空 []

发请求的例子

import React, {
    Component,
    useState,
    useEffect
} from 'react';

import axios from 'axios'

const Greeting = () => {
    const [data, setData] = useState({ hits: [] });

    useEffect(() => {
        const fetchData = async () => {
            const result = await axios(
                'http://hn.algolia.com/api/v1/search?query=redux',
            );

            setData(result.data);
        };

        fetchData();
    }, []);
    return (
        <ul>
            {data.hits.map(item => (
                <li key={item.objectID}>
                    <a href={item.url}>{item.title}</a>
                </li>
            ))}
        </ul>
    );
};
export default class Lifecycle extends Component {
    render() {
        return (<div>
            <Greeting/>
        </div>)
    }
}

Fragment 是什么

 <></> 是 <React.Fragment/> 的语法糖
<></> 语法不能接受键值或属性
import {Fragment} from 'react'
<Fragment></Fragment>

发现一个我没用过的三元表达式

a?3:void 0;
判断就是用
a=1
a&&2

搜索功能

import React, {
    Component,
    useState,
    useEffect,
    Fragment
} from 'react';

import axios from 'axios'

const Greeting = () => {
    const [data, setData] = useState({hits: []});// 数据
    const [query, setQuery] = useState('redux');//输入的关键字
    const [url, setUrl] = useState(//请求的url
        'http://hn.algolia.com/api/v1/search?query=redux',
    );
    useEffect(() => {
        const fetchData = async () => {
            const result = await axios(url);
            setData(result.data);
        };

        fetchData();
    }, [url]);
    return (<>
            <input type='text' value={query}
                   onChange={event => setQuery(event.target.value)}/>
            <button onClick={() =>
                setUrl(`http://hn.algolia.com/api/v1/search?query=${query}`)
            }>搜索
            </button>
            <ul>
                {data.hits.map(item => (
                    <li key={item.objectID}>
                        <a href={item.url}>{item.title}</a>
                    </li>
                ))}
            </ul>
        </>
    );
};

加loading

/*加loading*/
const [isLoading, setIsLoading] = useState(false);
useEffect(() => {
    const fetchData = async () => {
        setIsLoading(true);//加
        const result = await axios(url);
        setData(result.data);
        setIsLoading(false);//去掉
    };

    fetchData();
}, [url]);
页面
 {   isLoading?(<div>Loading...</div>):(数据)}

错误报错

  const [isError, setIsError] = useState(false);

  useEffect(() => {
    const fetchData = async () => {
      setIsError(false);
      setIsLoading(true);

      try {
        const result = await axios(url);

        setData(result.data);
      } catch (error) {
        setIsError(true);
      }

      setIsLoading(false);
    };

    fetchData();
  }, [url]);
页面
   {isError && <div>Something went wrong ...</div>}

通过表单也是可以的

  <form
        onSubmit={() =>
          setUrl(`http://hn.algolia.com/api/v1/search?query=${query}`)
          event.preventDefault();
        }
      >
        <input
          type="text"
          value={query}
          onChange={event => setQuery(event.target.value)}
        />
        <button type="submit">Search</button>
      </form>

封装成redux

const dataFetchReducer = (state, action) => {
  switch (action.type) {
    case 'FETCH_INIT':
      return { ...state };
    case 'FETCH_SUCCESS':
      return { ...state };
    case 'FETCH_FAILURE':
      return { ...state };
    default:
      throw new Error();
  }
};
再次修改后reducer
const dataFetchReducer = (state, action) => {
  switch (action.type) {
    case 'FETCH_INIT':
      return {
        ...state,
        isLoading: true,
        isError: false
      };
    case 'FETCH_SUCCESS':
      return {
        ...state,
        isLoading: false,
        isError: false,
        data: action.payload,
      };
    case 'FETCH_FAILURE':
      return {
        ...state,
        isLoading: false,
        isError: true,
      };
    default:
      throw new Error();
  }
};

const useDataApi = (initialUrl, initialData) => {
  const [url, setUrl] = useState(initialUrl);

  const [state, dispatch] = useReducer(dataFetchReducer, {
    isLoading: false,
    isError: false,
    data: initialData,
  });

  useEffect(() => {
    const fetchData = async () => {
      dispatch({ type: 'FETCH_INIT' });

      try {
        const result = await axios(url);

        dispatch({ type: 'FETCH_SUCCESS', payload: result.data });
      } catch (error) {
        dispatch({ type: 'FETCH_FAILURE' });
      }
    };

    fetchData();
  }, [url]);

useReducer

import React, {Component, useReducer} from 'react';

const initialState = {count: 0};

function reducer(state, action) {
    switch (action.type) {
        case 'increment': //初始化
            return {count: state.count + 1};
        case 'decrement':
            return {count: state.count - 1};
        case 'reset':
            return {count:action.payload}
    }
}

const Greeting = () => {
    const [state, dispatch] = useReducer(reducer, initialState,{
        type:'reset',payload:initialState
    });

    return   <>
        Count: {state.count}
        <button onClick={() => dispatch({type: 'increment'})}>+</button>
        <button onClick={() => dispatch({type: 'decrement'})}>-</button>
    </>
};

useContext

我还没理解
import React, {
    Component,
    useContext,
    createContext
} from 'react';

const FooContext = createContext('foo');
const BarContext = createContext('bar');

const Greeting = () => {
    const foo = useContext(FooContext);
    const bar = useContext(BarContext);
    return (
        <>
            <FooContext.Provider>
                <BarContext.Provider>
                    {foo}, {bar}
                </BarContext.Provider>
            </FooContext.Provider>
        </>
    )
};

#################################################################......................................................................................................................................................................##########################################################################################....................................................................................................................................................