【问题标题】:Refactoring React class to hooks - Entity update component将 React 类重构为钩子 - 实体更新组件
【发布时间】:2020-08-13 17:09:08
【问题描述】:

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

这是之前的代码

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>
  );
}

【问题讨论】:

  • 你想把一个基于类的组件转换成函数式组件然后在里面使用你自己的两个自定义钩子是什么意思?
  • 我的意思是使用 hook/s 实现相同的功能。我添加了指向我创建的挂钩的链接,只是为了尝试提供一些上下文。我不一定想使用它们。我相信理想情况下我会创建一个用来获取和更新实体的钩子。

标签: javascript reactjs react-hooks use-effect use-state


【解决方案1】:

我尚未对此进行测试,但这应该接近您想要的实体函数自定义钩子。

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>
    )
}

【讨论】:

    【解决方案2】:

    感谢 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>
      );
    }
    

    【讨论】:

      猜你喜欢
      • 2020-10-15
      • 2019-08-08
      • 2020-09-26
      • 1970-01-01
      • 1970-01-01
      • 2020-06-01
      • 1970-01-01
      • 1970-01-01
      • 2019-12-12
      相关资源
      最近更新 更多