如何将钩子导出到react.js中的其他函数?

时间:2020-10-28 23:28:21

标签: reactjs react-hooks

我试图将钩子{count,setCount} = useState(0)导出到另一个函数,以便能够获取{count}值。 我的应用程序是通过添加项目来制作简单的清单,然后按“提交”按钮获取该清单的渲染。

import React, { useState } from "react";
import objects from "../list";

const List = function _List(item) {
  const [count, setCount] = useState(0);
  const increase = () => {
    return count < 10 ? setCount(count + 1) : 10;
  };
  const decrease = () => {
    return count > 0 ? setCount(count - 1) : 0;
  };
  return (
    <div className="flex">
      <h3>{item.name}</h3>
      <button type="submit" onClick={decrease}>
        -
      </button>
      <h3>{count}</h3>
      <button type="submit" onClick={increase}>
        +
      </button>
    </div>
  );};

function App() {
  const [message, setMessage] = useState("No Order Submited");

  function displayOrder() {
    const orderList = setMessage(objects.map((x) => `${x.name} `));
    // Would like to export {count} in const orderList
    return { orderList };
  }

  return (
    <div>
      <fieldset>
        <h1>Items:</h1>
        {objects.map(List)}
      </fieldset>
      <button type="submit" onClick={displayOrder}>
        Submit
      </button>
      <h2>{message}</h2>
    </div>
  );
}
export default App;

这是我的清单的对象列表:

const objects = [
  {
    id: 1,
    name: "item1",
  },
  {
    id: 2,
    name: "item2",
  }
];
export default objects;

最好的方法是将我的钩子移到App函数中,但是增加或减少{count}会影响我的所有商品。

运行displayOrder函数时,是否仍要为每个项目渲染{count}?

谢谢!

1 个答案:

答案 0 :(得分:0)

您可能要执行的主要方法是将状态移到父组件。像这样:

const {useState} = React;
const exampleObjects = [
  {id: 1, name: "item1"},
  {id: 2, name: "item2"}
];

// It makes react devs happy when you avoid mutating state.
const update = (arr, i, newVal) => [
  ...arr.slice(0,i), newVal, ...arr.slice(i+1)
];

function List({name, count, setCount}) {
  const increase = () => {
    return count < 10 ? setCount(count + 1) : 10;
  };
  const decrease = () => {
    return count > 0 ? setCount(count - 1) : 0;
  };

  return (
    <div className="flex">
      <h3>{name}</h3>
      <button type="submit" onClick={decrease}>
        -
      </button>
      <h3>{count}</h3>
      <button type="submit" onClick={increase}>
        +
      </button>
    </div>
  );
}

function App({objects}) {
  // I would actually recommend you make counts an object, but I figured I'd leave the .reduce fun as an exercise for you.
  // Note this also gets rid of the update function silliness, allowing you to do something like {...oldObj, [id]: newVal} instead. 
  const [counts, setCounts] = useState(objects.map(_ => 0));
  const [order, setOrder] = useState(null);

  const setCount = (i) => (newVal) => {
    setCounts(cs => update(cs,i,newVal));
  };

  const submitOrder = () => {
    setOrder(objects.map((o,i) => ({...o, count: counts[i]})));
  };

  return (
    <div>
      <fieldset>
        <h1>Items:</h1>
        {objects.map((o, i) => (<List key={o.id} {...o} count={counts[i]} setCount={setCount(i)} />))}
      </fieldset>
      <button type="submit" onClick={submitOrder}>
        Submit
      </button>
      <h2>Orders</h2>
      {!order ? "No order submitted" : order.map(({id, name, count}) => (
          <div key={id}> {name}: {count} </div>
      ))}
    </div>
  );
}


// Render it
ReactDOM.render(
  <App objects={exampleObjects} />,
  document.getElementById("react")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="react"></div>