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]);