0

I have a parent component, that render one child component several time. This child component is used in many different components. I need to have an array in this child component that keeps all the previous renders of the component, then get access to the largest text passed to it.

import TextComponent from '../../text'
const ParentComponent = ()=>{
  // ... some code here and get some data from API
 const text = getTextFromAPI()
  return (
   <>
    <ARandomComponent/>
    <AnotherRandomComponent/>
    <TextComponent text={text}/>
  </>)
}

In the TextComponent I need to know what text each element received, and return the largest text. I thought maybe I can have an array inside TextComponent but of course with each render, component has fresh data and I know this is by design.

Is there any way to active this? To store a value in the TextComponent that other renders from different places still have access to that value

Beekman
  • 13
  • 3
  • If I understood you correctly, you want to share some state between all instances of the `TextComponent`? In such case, store the array as state in the parent component. – zhulien Dec 07 '21 at 11:01
  • The problem is that there are several parents. This `TextComponent` is getting used in 15 different parent components, I don't want to duplicate the logic in each parent component, and that's why I was looking for a way to implement it inside the `TextComponent` @zhulien – Beekman Dec 07 '21 at 11:05
  • @Jax-p I think you did not correctly understand what I meant. The `TextComponent` is getting rendered in 15 different places, and I don't want to place the logic in the parent components. But I need the `TextComponent` itself keep track of its other instances – Beekman Dec 07 '21 at 11:07
  • A different instance of the component will be used in each component that use TextComponent. It's not like a global component that any component can refer to. What you can do is using a context that each of the TextComponent will be connected to via a hook and that way you can communicate with all the TextComponent components. But then again, I'm not sure whether I understood correctly. – jperl Dec 07 '21 at 11:13
  • @Beekman In such case, you should either store the shared state in a context (check out https://reactjs.org/docs/context.html) or a custom service and fetch the data in your `TextComponent`s from there. – zhulien Dec 07 '21 at 11:18
  • @zhulien What do you mean by a custom service? – Beekman Dec 07 '21 at 12:19

3 Answers3

0

If your ParentComponent isn't re-rendering. You could use a useState with a condition on calling your setState that the actual state is smaller than the new text you're gonna receive.

  • No, actually the problem is not about re-rendering only. It's about the `TextComponent` getting rendered in 15 different parent components. It's a shared component, and I want it to be standalone and work by itself and know the longest text passed to it without duplicating the logic in several parent components – Beekman Dec 07 '21 at 11:09
  • Then inside your TextComponent use a `useState` to keep your data and use a `useEffect` with your `text` prop in the dependency array. Do your logic here to see if you got the largest string or not and update the state – Alexis - Anae Dec 07 '21 at 11:20
0

You need to use state management tools like redux which makes your state available app wide. Fetch the data and store the array in a redux state. Then it is accessible from any component throughout the app.

bgcodes
  • 248
  • 2
  • 12
0

Edit: You clarified in a comment the requirement for a "global" value used by multiple components. This is a case for using the builtin Context API or a state management library like Recoil or Effector.


You can use a hook like this to store the longest string seen during the lifespan of the component which used it:

function useLongestString (text = '') {
  const [str, setStr] = useState(text);
  if (text.length > str.length) setStr(text);
  return str;
}

Demo:

<div id="root"></div><script src="https://unpkg.com/react@17.0.2/umd/react.development.js"></script><script src="https://unpkg.com/react-dom@17.0.2/umd/react-dom.development.js"></script><script src="https://unpkg.com/@babel/standalone@7.16.4/babel.min.js"></script>
<script type="text/babel" data-type="module" data-presets="react">

const {useState} = React;

function useLongestString (text = '') {
  const [str, setStr] = useState(text);
  if (text.length > str.length) setStr(text);
  return str;
}

function DisplayLongestString (props) {
  const longest = useLongestString(props.text);
  return <div>{longest}</div>;
}

function Example (): ReactElement {
  const [value, setValue] = useState('Keep typing');
  return (
    <div>
      <h2>Longest string:</h2>
      <DisplayLongestString text={value} />
      <input
        onChange={ev => setValue(ev.target.value)}
        placeholder="Type a longer string"
        value={value}
      />
    </div>
  );
}

ReactDOM.render(<Example />, document.getElementById('root'));

</script>
jsejcksn
  • 27,667
  • 4
  • 38
  • 62
  • This would not work as he'll need to use the hook arbitrary number of times and each usage creates its own brand new state which is independent of the other usages. – zhulien Dec 07 '21 at 11:23
  • 1
    @zhulien Thanks for making me aware of something that wasn't written in the question. – jsejcksn Dec 07 '21 at 11:34