Home > other >  How to export or use component state as hook
How to export or use component state as hook

Time:11-08

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

  • Related