简体   繁体   中英

How to pass states to components in React without each passed state being same reference

I'm attempting to pass states down to a few components through a clicking counter. So I can click a counter that increments the value of the count state and if i stop at say 10 and send that to a component, I want the next time i use the counter and set it to 15 this time, I need to have it send it to another component (or the same one) but now the count state is 15. I don't want to have both instances of the state be set to 15. Each state should keep their numbers.

JSX

<div className="addnum" onClick={() => addUnits()}>+</div>

JS

const [units,setUnits] = useState(0)
function addUnits() {
    setUnits(prev => prev+1)
} 

Some Component 1

<div>{units}</div>

Some Component 2

<div>{units}</div> 

My issue is when i set the state of one, the other one receives the same state, which is normal. How can i remove the reference or create copies of each state so they are individual?

I saw this post which answers the question when using class based components but my state isn't an array so how can i do the same thing here? https://stackdev.io/question/434/copy-the-state-in-react-without-reference

As I understand. You have the list of counters and the list of so called Some Components. So the straightforward data structure in such a case is array. Also, timer is needed to create new slot after some downtime. useReducer is a preferable way to handle non-scalar state. Something like the following:

const initialState = [0];

function reducer(state, action) {
  const [head, ...tail] = state;
  switch (action.type) {
    case 'inc':
      return [head + 1, ...tail];
    case 'new':
      return [0, ...state];
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  const timer = useRef(null);
  const inc = useCallback(() => {
    if (timer.current) clearTimeout(timer.current);
    timer.current = setTimeout(() => dispatch({type: 'new'}), 1000);
    dispatch({type: 'inc'});
  }, [timer, dispatch]);
  useEffect(() => () => {
    if (timer.current) clearTimeout(timer.current);
  });
  return (
    <>
      {state.map((count, i) => <div key={i}>{count}</div>)}
      <button onClick={inc}>+</button>
    </>
  );
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM