将 React class 重构为 hooks - 实体更新组件

Refactoring React class to hooks - Entity update component

我有这个用于更新业务实体的 React 组件。它基本上通过 componentDidMount 上的 ID 获取,并在提交表单时发送放置请求。我想将其重构为基于钩子的组件。

这是之前的代码

import React from "react";
import axios from "axios";

//Api Helper Methods
const API_HOST = "https://api.example.com";
const get = (endPoint) =>
  axios
    .get(`${API_HOST}/${endPoint}`)
    .then((response) => response.data);

export const put = (endPoint, payload, id) =>
  axios
    .put(`${API_HOST}/${endPoint}/${id}`, payload)
    .then((response) => response.data);

//React route (uses React Router)
const END_POINT = `users`;

class Entity extends React.Component {

  state = { entity: {}, fetching: true };

  getEntity = async () => {
    const { id } = this.props.match.params;
    this.setState({ fetching: true });
    const entity = await get(`${END_POINT}/${id}`);
    this.setState({ entity, fetching: false });
  };

  onChange = (key, value) =>
    this.setState({ entity: { ...this.state.entity, [key]: value } });

  componentDidMount() {
    this.getEntity();
  }

  onSubmit = async (e) => {
    e.preventDefault();
    let { entity } = this.state;
    let { match } = this.props;
    await put(END_POINT, entity, match.params.id);
  };

  render() {
    const { entity, fetching } = this.state;

    if (fetching) {
      return <p>loading...</p>;
    }

    return (
      <form onSubmit={this.onSubmit}>
        <label htmlFor="name">name</label>
        <input
          value={entity["name"]}
          onChange={(e) => this.onChange("name", e.target.value)}
        />
        <button type="submit">submit</button>
      </form>
    );
  }
}

export default Entity;

这就是我到目前为止的代码。下一步是提取自定义挂钩。

const END_POINT = `users`;

export default function Entity({ match }) {
  const [entity, setEntity] = useState({ name: "" });
  const [fetching, setFetching] = useState( true );
  const { id } = match.params;

  const onChange = (key, value) => setEntity({ ...entity, [key]: value });

  useEffect(() => {
    const fetchEntity = async () => {
      const entity = await get(`${END_POINT}/${id}`);
      setEntity(entity);
      setFetching(false);
    };
    fetchEntity();
  }, [id]);

  const onSubmit = async (e) => {
    e.preventDefault();
    await put(END_POINT, entity, id);
  };

  if (fetching) {
    return <p>loading...</p>;
  }

  return (
    <form onSubmit={onSubmit}>
      <label htmlFor="name">name</label>
      <input
        value={entity["name"]}
        onChange={(e) => onChange("name", e.target.value)}
      />
      <button type="submit">submit</button>
    </form>
  );
}

我还没有对此进行测试,但这应该接近您想要的实体函数自定义挂钩。

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

const API_HOST = "https://api.example.com";
const END_POINT = `users`;

function useEntity(entityID) {
    const [entity, setEntity] = useState({})
    
    
    useEffect(() => {
        (async () => {
            await fetch(`${API_HOST}/${END_POINT}/${props.match.params}`)
                .then(async res => await res.json())
                .then(result => setEntity(result));
        })();
    }, [])

    return entity
}

export default function Entity(props) {
    const { id } = props.match;
    const entity = useEntity(id);
    const onSubmit = async () => await fetch(`${API_HOST}/${END_POINT}/${id}`, {method: 'PUT', body: entity})

    if (!entity) {
        return <p>loading...</p>;
    }

    return (
        <form onSubmit={onSubmit}>
            <label htmlFor="name">name</label>
            <input
            value={entity["name"]}
            onChange={(e) => setEntity({ ...entity, name: e.target.value})}
            />
            <button type="submit">submit</button>
        </form>
    )
}

感谢 Harben 的帮助,我就这样搞定了。

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

//Api Helper Methods
const API_HOST = "https://api.example.com";

const get = (endPoint) =>
  axios.get(`${API_HOST}/${endPoint}`).then((response) => response.data);

export const put = (endPoint, payload, id) =>
  axios
    .put(`${API_HOST}/${endPoint}/${id}`, payload)
    .then((response) => response.data);


const END_POINT = `users`;

const useEntity = (entityId) => {
  const [entity, setEntity] = useState({ name: "" });
  const [fetching, setFetching] = useState(true);

  useEffect(() => {
      (async () => {
        const entity = await get(`${END_POINT}/${entityId}`);
        setEntity(entity);
        setFetching(false);
    })();
  }, [entityId]);

  return [entity, fetching, setEntity];
};

//React route (uses React Router)
export default function Entity({ match }) {
  const { id } = match.params;
  const [entity, fetching, setEntity] = useEntity(id);

  const onChange = (key, value) => setEntity({ ...entity, [key]: value });

  const onSubmit = async (e) => {
    e.preventDefault();
    await put(END_POINT, entity, id);
  };

  if (fetching) {
    return <p>loading...</p>;
  }

  return (
    <form onSubmit={onSubmit}>
      <label htmlFor="name">name</label>
      <input
        value={entity["name"]}
        onChange={(e) => onChange("name", e.target.value)}
      />
      <button type="submit">submit</button>
    </form>
  );
}