Home > Software design >  Object is undefined outside a return statement, but is accessible in a component
Object is undefined outside a return statement, but is accessible in a component

Time:08-04

I'm curious as to why useState is giving me undefined for something that can be used inside JSX:

The following is outside the return statement:

useEffect(() => dispatch(fetchMessages()), [dispatch]);

const isLoading = useLoadingState(ApiAction.fetchMessages);
const { messages } = useSelector<MessagesState>((state) => state.messages);
const [filteredMessages, setFilteredMessages] = useState<AdminMessages[]>();
useEffect(() => setFilteredMessages(messages), [messages]);

And while messages is an array of objects, filteredMessages is undefined

However, filteredMessages can be rendered inside the return statement in an ant-design components as follows:

return (
  <Table
    rowClassName="Table__row"
    dataSource={filteredMessages}
    rowKey="id"
    pagination={false}
  >
  // etc.

Why is filteredMessages undefined outside the return statement, but is then accessible inside when fed into the component?

CodePudding user response:

At the moment you create filteredMessages state and update it using useEffect. State updates are not visible immediately - instead they will trigger new re-render and then with the next component call the updated state will be passed.

So in your case I recommend handling undefined case and defaulting to messages:

return (
  <Table
    rowClassName="Table__row"
    dataSource={filteredMessages || messages}
    rowKey="id"
    pagination={false}
  >
  // etc.

You can also set initial state by passing messages to useState function. By default initial state is undefined.

CodePudding user response:

The first argument of useState is the "initial state" value. You didn't pass in an initial value, so the initial value is undefined:

const [filteredMessages, setFilteredMessages] = useState<AdminMessages[]>();

During the initial render, the returned state (state) is the same as the value passed as the first argument (initialState).

However, later on you call setFilteredMessages() which then sets the state:

useEffect(() => setFilteredMessages(messages), [messages]);
  • Related