Delrog
Delrog

Reputation: 765

React UseSelector with render upon variable change

I'm attempting to retrieve a filtered array from state with Redux based on a selected value (selectedNum) in the component. However, the re-render doesn't seem to fire to call the useSelector after the selectNumberHandler has fired.

I've attempted to filter the numbers array in the handler itself but that didn't seem to filter the rendered numbers in the global scope either.

I've also tried adding the following to no avail (doesn't hit the debugger point after setting the var in the onChange):

  useEffect(() => {
    debugger;
  }, [selectedNum]);

Could you please assist me in finding a solution and best practices for this sort of thing?

const MyFunction = () => {
  let selectedNum: number;
  let numbers = useSelector(filterNumbers(selectedNum));

  const selectNumberHandler (selectedValue) => {
      selectedNum = selectedValue;
  }

  return (
    <div>
      <select onChange={e => selectNumberHandler(e)}>
        <option value='1' >1</option>
        <option value='2' >2</option>
      </select>
      <div className={'numbers-list'}>
        {numbers.map(num => {
          <p>{num}</p>;
        })}
      </div>
    </div>
  );
};

Upvotes: 1

Views: 3067

Answers (1)

Seth Lutske
Seth Lutske

Reputation: 10696

useSelector takes a function of state as the argument. State being the state of the redux store. Like this:

const numbers = useSelector(state => somewhereinstate.number);

In this way, we can select variables out of the redux store. What you seem to be trying to do is update the selectedNum variable. But I don't see where you're dispatching that update to the store. Your useEffect doesn't fire because it depends on selectedNum. Your selectNumberHandler might alter selectedNum, but your component doesn't know that, because selectedNum is not a state variable in the component.

So you kind of need to decide: are you keeping the state local to the component, or are you communicating through the store?

Local to the component - no useSelector

const MyFunction = () => {

  const [selectedNumber, setSelectedNumber] = useState(1)
  const [filteredNumbers, setFilteredNumbers] = useState([])

  useEfect( () => {
    setFilteredNumbers(selectedNumber)
  }, [selectedNumber])

  return (
    <div>
      <select onChange={e => setSelectedNumber(e.value)}>
        <option value='1' >1</option>
        <option value='2' >2</option>
      </select>
      <div className={'numbers-list'}>
        {filteredNumbers.map(num => {
          <p>{num}</p>;
        })}
      </div>
    </div>
  );
};

Through redux store, with useDispatch and useSelector


const MyFunction = () => {

  const numbers = useSelector(state => state.yourValues);
  const dispatch = useDispatch()


  return (
    <div>
      <select onChange={e => dispatch( setYourValues(e.value) )}>
        <option value='1' >1</option>
        <option value='2' >2</option>
      </select>
      <div className={'numbers-list'}>
        {numbers.map(num => {
          <p>{num}</p>;
        })}
      </div>
    </div>
  );
};

where setYourValue is a function that creates an action to update the yourValue in the redux store.

Hopefully that gives you some direction.

Upvotes: 1

Related Questions