I want to use hook to get and set the value of my component WITHOUT PROPS. I import the component and it lists the data returned from the request, ok, but when I use the hook to see the data it returns empty, as if it were another instance.
Initially I used the state of the parent component, but when I needed to change some value of my component, everything would re-render as it affected the state of the parent component, so I want to isolate the state in the child component and use it freely as a hook elsewhere .
How I would like to use:
import MyComp, { useMyHook } from '../../../components/MyComp';
const OtherComp = () => {
const { data } = useMyHook();
return(
<div>
<button type="button" onClick={() => console.log(data)}>
click test
</button>
<MyComp />
</div>
);
};
export default OtherComp;
Component render
Example1
Example2
But the click button log: [ ]
Without using external components/libs like redux and etc.
My custom hook: src/useMyHook.ts
import { useState } from 'react';
export const useMyHook = () => {
const [data, setData] = useState<any[]>([]);
const addItem = (item: unknown) => {
setData([...date, item]);
};
return { data, setData, addItem};
};
export default useMyHook;
My main component: src/MyComp.tsx
import {useEffect} from 'react';
import useMyHook from './useMyHook';
const MyComp = () => {
const { data, setData } = useMyHook();
const req = async() => {
const {values} = await anyRequest(); // to do any request
setData(values);
};
useEffect(() => { req() },[]);
return(
<div>
{data.map((item) => <p>{item.name}</p>)}
</div>
);
};
export { useMyHook };
export default MyComp;
src/index.tsx
import MyComp, { useMyHook } from './MyComp';
export default MyComp;
export { useMyHook };
CodePudding user response:
To demonstrate my comment:
import React,{useState, createContext} from 'react';
import { Text, View, StyleSheet, Button } from 'react-native';
import Constants from 'expo-constants';
import useMyHook from './useMyHook'
import Example1 from './Example1'
import Example2 from './Example2'
import OtherComp from './OtherComp'
import {Data, DataSetter} from './types'
type DContext = {
data:Data,
setData:DataSetter
}
export const DataContext = createContext({
data:[],
setData:()=>{}
} as DContext)
export default function App() {
const [data, setData] = useState<Data>([])
return (
<View style={styles.container}>
<DataContext.Provider value={{data,setData}}>
<Example1/>
<Example2/>
<OtherComp/>
</DataContext.Provider>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
padding: 8,
},
paragraph: {
margin: 24,
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
});
import { useContext, useCallback } from 'react';
import { DataContext } from './App';
export const useMyHook = () => {
const { data, setData } = useContext(DataContext);
// wrapped in useCallback to prevent function from
// being recreated
const addItem = useCallback((item: unknown) => {
setData(prev=>[...prev, item]);
},[]);
return { data, setData, addItem };
};
export default useMyHook;
useMyHook
usage:
import React, { useEffect } from 'react';
import { View, Button } from 'react-native';
import useMyHook from './useMyHook';
export default function Example1() {
const { data, addItem } = useMyHook();
return (
<View style={{ width: '100%' }}>
<Button
title="Add Item From Example 1"
onPress={() => {
addItem(Math.floor(Math.random() * 25) ' From Example1');
}}
/>
</View>
);
}
A demo