REACT:如何创建一个可重用的自定义挂钩,其功能和效果可以更改并对主机组件数据的更改做出反应
REACT: How to create a reusable custom hook with functions and effects that can change & react to changes in a host component's data
我有一个用于编辑订单信息(客户名称、商品、地址等)的 React App 组件
- 使用将订单数据和事件处理程序作为属性的子组件显示地址。
- 地址数据的更改由 useEffects 在主机组件 (App) 中处理。
- 还有地址相关的辅助函数可以调用
- 其他 App 子组件也使用订单数据与它的其他部分一起工作。
这里是简化版...
function App({ orderInfo }) {
// App state ('data' has customer name, address, user role, etc.)
const [data, setData] = useState(orderInfo);
// Address-related functions & effects:
function isEditableAddress() { return data.user.role === 'EDITOR' }
useEffect(function loadSuburb() {
// (Load suburb when postcode changes)
(async () => {
const response = await fetch(`/myApp/getSuburb.do&postCode=${data.postcode}`);
const suburb = await response.json();
setData((prev) => ({...prev, suburb: suburb}));
})();
},[data.postcode]);
// -- Non-address functions & effects:
// [here go more functions & effects that also work with 'data'...]
// Sub-components, one of which works with address...
return (
<>
<AddressComponent
data={data}
isEditableAddress={isEditableAddress()}
onChangePostcode={val => {setData((prev) => ({...prev, postcode: val}))}}
/>
<OtherComponent
data={data}
onChangeFirstname={val => {setData((prev) => ({...prev, firstname: val}))}}
/>
</>
);
}
我现在有另一个应用程序需要使用 AddressComponent 和相同的地址效果和功能(其中比上面的示例更多)所以我倾向于将它们移动到...自定义挂钩中?
我的问题是:
如何让 'useEffect(fn, [data.postcode])' 在父组件位于其自己的自定义挂钩中后对数据做出反应并更新数据? (我尝试将 'data' 和 'setData' 作为属性传递到我的 useAddress 自定义挂钩中,但没有成功。)
如何将辅助函数暴露给父组件?我是否只是 return 它们来自自定义挂钩,并将它们设置在主组件中,如:{isEditableAddress} = useAddressHook();
或者我对自定义挂钩的期望很高?最好的方法是什么?我正在努力寻找以这种方式工作的自定义挂钩的示例。
自定义挂钩旨在完全按照您的需要^隔离和重用其逻辑。您可以在 React 官方文档中阅读更多关于 building custom hooks 的信息。您的案例是构建自定义挂钩的典型案例:隔离状态、效果和一些函数以在一个挂钩中对状态进行操作。你可以这样做:
const useOrderData = (initialState) => {
const [orderData, setOrderData] = useState(initialState)
useEffect(() => {
// load suburb
setOrderData()
}, [data.postcode])
// other effects in case you need them
const isEditableAddress = orderData.user.role === 'EDITOR'
return [orderData, { isEditableAddress }]
}
您还可以向自定义挂钩添加一些函数,我将 isEditableAddress
更改为变量,因为每次数据更改时它的值都会更新。使用钩子将如下所示:
const [data, { isEditableAddress }] = useOrderData({})
检查这个site,有很多自定义钩子示例
我有一个用于编辑订单信息(客户名称、商品、地址等)的 React App 组件
- 使用将订单数据和事件处理程序作为属性的子组件显示地址。
- 地址数据的更改由 useEffects 在主机组件 (App) 中处理。
- 还有地址相关的辅助函数可以调用
- 其他 App 子组件也使用订单数据与它的其他部分一起工作。
这里是简化版...
function App({ orderInfo }) {
// App state ('data' has customer name, address, user role, etc.)
const [data, setData] = useState(orderInfo);
// Address-related functions & effects:
function isEditableAddress() { return data.user.role === 'EDITOR' }
useEffect(function loadSuburb() {
// (Load suburb when postcode changes)
(async () => {
const response = await fetch(`/myApp/getSuburb.do&postCode=${data.postcode}`);
const suburb = await response.json();
setData((prev) => ({...prev, suburb: suburb}));
})();
},[data.postcode]);
// -- Non-address functions & effects:
// [here go more functions & effects that also work with 'data'...]
// Sub-components, one of which works with address...
return (
<>
<AddressComponent
data={data}
isEditableAddress={isEditableAddress()}
onChangePostcode={val => {setData((prev) => ({...prev, postcode: val}))}}
/>
<OtherComponent
data={data}
onChangeFirstname={val => {setData((prev) => ({...prev, firstname: val}))}}
/>
</>
);
}
我现在有另一个应用程序需要使用 AddressComponent 和相同的地址效果和功能(其中比上面的示例更多)所以我倾向于将它们移动到...自定义挂钩中?
我的问题是:
如何让 'useEffect(fn, [data.postcode])' 在父组件位于其自己的自定义挂钩中后对数据做出反应并更新数据? (我尝试将 'data' 和 'setData' 作为属性传递到我的 useAddress 自定义挂钩中,但没有成功。)
如何将辅助函数暴露给父组件?我是否只是 return 它们来自自定义挂钩,并将它们设置在主组件中,如:{isEditableAddress} = useAddressHook();
或者我对自定义挂钩的期望很高?最好的方法是什么?我正在努力寻找以这种方式工作的自定义挂钩的示例。
自定义挂钩旨在完全按照您的需要^隔离和重用其逻辑。您可以在 React 官方文档中阅读更多关于 building custom hooks 的信息。您的案例是构建自定义挂钩的典型案例:隔离状态、效果和一些函数以在一个挂钩中对状态进行操作。你可以这样做:
const useOrderData = (initialState) => {
const [orderData, setOrderData] = useState(initialState)
useEffect(() => {
// load suburb
setOrderData()
}, [data.postcode])
// other effects in case you need them
const isEditableAddress = orderData.user.role === 'EDITOR'
return [orderData, { isEditableAddress }]
}
您还可以向自定义挂钩添加一些函数,我将 isEditableAddress
更改为变量,因为每次数据更改时它的值都会更新。使用钩子将如下所示:
const [data, { isEditableAddress }] = useOrderData({})
检查这个site,有很多自定义钩子示例