3

使用自定义hooks封装数据获取逻辑

const useData = (url) => {
  const [data, setData] = useState([]);

  useEffect(() => {
    fetch(url)
      .then((response) => (response.json ? response.json() : response))
      .then((data) => {
        setData(data);
      });
  }, [url]);

  return {
    data,
  };
};

渲染数据

function List(props) {
  const { data } = props;

  return data.map((item) => <div key={item.id}>{item.description}</div>);
}

function App() {
  const { data } = useData('https://api.github.com/users/gaearon/gists');

  return <List data={data} />;
}

分离列表和单个列表项的职责

List是一个列表组件,它的职责是渲染列表,但这里我们额外的处理了单个列表项的渲染。

更好的做法是将这部分进行分离,List只渲染列表,单个列表项的渲染细节抽离出来。

function ListItem(props) {
  const { description } = props;

  return <div>{description}</div>;
}

function List(props) {
  const { data } = props;

  return data.map((item) => (
    <ListItem key={item.id} description={item.description} />
  ));
}

List和ListItem之间的耦合

观察上面的List组件,我们会发现ListItem被耦合在了List内部,当我们需要更换不同的ListItem时,需要深入到List中进行修改,这会引入风险。

下面我们采用render prop模式来解决这个问题。

function ListItem(props) {
  const { description } = props;

  return <div>{description}</div>;
}

function List(props) {
  const { data, renderItem } = props;

  return data.map(renderItem);
}

function App() {
  const { data } = useData('https://api.github.com/users/gaearon/gists');

  return (
    <List
      data={data}
      renderItem={(item) => (
        <ListItem key={item.id} description={item.description} />
      )}
    />
  );
}

List现在不用关心列表项是什么了,它只需要执行renderItem,并且还能适应未来各种不同的ListItem


热饭班长
3.7k 声望434 粉丝

先去做,做出一坨狗屎,再改进。