Reputation: 81
I am building a table component. It gets as a prop an object called content which holds records that are displayed as the table's content. The component has a state called 'currentRecord' which holds the id of the selected row (changes in onClick event on each row). I want to set the first record's id to be the initial state using the 'useState'. As an initial state argument for the 'useState' it has a function which return the key(which is the id) of the first record in the content prop. But it returns undefined. When console logging the return value of that function, it return an id. Why does it return undefined when setting the initial state using a function?
I have tried setting the initial state using a string instead of a function, and it worked.
function getFirstOrderId(content:object): string {
return Object.keys(content)[0];
}
const Table: FunctionComponent<Props> = props => {
const { columnTitles, content, onRowClick } = props;
const [currentRecord, setCurrentRecord] = useState(getFirstOrderId(content));
useEffect(() => {
onRowClick(currentRecord);
}, [currentRecord]);
return (
<StyledTable>
<thead>
<tr>
{Object.values(columnTitles).map(fieldName => {
return <th>{fieldName}</th>;
})}
</tr>
</thead>
<StyledTBody>
{mapWithKeys((order: any, id: string) => {
return (
<StyledRow
key={id}
isSelected={id === currentRecord}
onClick={() => setCurrentRecord(id)}
onDoubleClick={() => window.open("/" + order)}
>
{Object.keys(columnTitles).map(fieldContent => {
return <td>{order[fieldContent]}</td>;
})}
</StyledRow>
);
}, content)}
</StyledTBody>
</StyledTable>
);
};
export default Table;
Upvotes: 5
Views: 12773
Reputation: 314
Put a function inside the useState hook and return the value.
const [value, setValue] = useState(() => ({key: "Param"}));
console.log(value) // output >> {key: "Param"}
Upvotes: 3
Reputation: 724
You can actually do lazy initialisation to state with a function. how ever you called the function and not passed in as a parameter, meaning you passed the returned value of the function as the initial value to use state. You can check out the official explanation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/all
Upvotes: 0
Reputation: 31495
This might work:
const [currentRecord, setCurrentRecord] = useState(null);
useEffect(()=>{ // This will run after 1st render
setCurrentRecord(getFirstOrderId(content)); // OPTION 1
setCurrentRecord(()=>{ // OPTION 2
return getFirstOrderId(content);
});
},[]);
You can set up a loading
state to wait for the useEffect()
to take place.
Upvotes: 2