useReducer结合useContext

2020-07-03  本文已影响0人  西域战神

1.初始化

首先创建Users,Books,Movies以及App组件

import React from "react";
import ReactDOM from "react-dom";

function App() {
  return (
    <div>
      <User />
      <hr />
      <Books />
      <Movies />
    </div>
  );
}

function User() {
  return (
    <div>
      <h1>个人信息</h1>
      <div>name:</div>
    </div>
  );
}

function Books() {
  return (
    <div>
      <h1>我的书籍</h1>
      <ol>
        <li>Effective Java</li>
        <li>Introduction Java</li>
      </ol>
    </div>
  );
}

function Movies() {
  return (
    <div>
      <h1>我的电影</h1>
      <ol>
        <li>蝙蝠侠</li>
        <li>复仇者联盟</li>
      </ol>
    </div>
  );
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
image.png

创建一个默认store,reducer以及context

const Context = React.createContext(null);
const store = {
  user: null,
  books: null,
  movies: null
};
const reducer = (state, action) => {
  switch (action.type) {
    case "setUsers":
      return { ...state, users: action.users };
    case "setMovies":
      return { ...state, movies: action.movies };
    case "setBooks":
      return { ...state, books: action.books };
    default:
      throw new Error();
  }
};

使用useReducer创建读写api,然后将其放入context中

function App() {
  const [state,dispatch] = useReducer(reducer,store)
  return (
    <Context.Provider value={{state,dispatch}}>
      <User />
      <hr />
      <Books />
      <Movies />
    </Context.Provider>
  );
}

写一个mock的fetch函数

function fetch(path) {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      if (path === "/user") {
        resolve({
          id: 1,
          name: "Larry"
        });
      } else if (path === "/books") {
        resolve([
          {
            id: 1,
            name: "Effective Java"
          },
          {
            id: 2,
            name: "Introduction Java"
          }
        ]);
      } else if (path === "/movies") {
        resolve([
          {
            id: 1,
            name: "复仇者联盟"
          },
          {
            id: 2,
            name: "蝙蝠侠"
          }
        ]);
      }
    }, 2000);
  });
}

在User组件中调用fetch,并且触发dispatch

function User() {
  const { state, dispatch } = useContext(Context);
  useEffect(()=>{
    fetch("/user").then(users => {
      dispatch({ type: "setUsers", users });
    });
  },[])

  return (
    <div>
      <h1>个人信息</h1>
      <div>name:{state.user ? state.user.name : ""}</div>
    </div>
  );
}

这时我们成功触发了'setUsers'的dispatch,可以正确显示结果.
同理,我们可以'setbooks'和'setMovies'


function Books() {
  const { state, dispatch } = useContext(Context);
  useEffect(() => {
    fetch("/books").then(books => {
      console.log(books);
      dispatch({ type: "setBooks", books: books });
    });
  }, []);
  return (
    <div>
      <h1>我的书籍</h1>
      <ol>
        {state.books
          ? state.books.map(book => <li key={book.id}>{book.name}</li>)
          : "加载中"}
      </ol>
    </div>
  );
}

function Movies() {
  const { state, dispatch } = useContext(Context);
  useEffect(() => {
    fetch("/movies").then(movies => {
      dispatch({ type: "setMovies", movies: movies });
    });
  }, []);
  return (
    <div>
      <h1>我的电影</h1>
      <ol>
        {state.movies
          ? state.movies.map(movie => <li key={movie.id}>{movie.name}</li>)
          : "加载中"}
      </ol>
    </div>
  );
}
image.png
上一篇 下一篇

猜你喜欢

热点阅读