Reputation: 321
i am trying to set value of an array after being filter as the default value of useState, here is the sample code:
var { studentList } = useContext(StudentListContext);
var selectedWarningStudents = flattenScoreList(studentList).filter((item) => {
return selected.includes(item._id);
});
debugger
var [mailList, setMailList] = useState(selectedWarningStudents);
console.log('mailList', mailList);
this is what it printed after set debugger, as you can see, array "studentList" has 91 items, array "selectedWarningStudents" has 3 items match with 3 item in the array "selected". So nothing is unexpected here
after get the array "selectedWarningStudents" i want to set its value as default value in the useState that i set below
but when i log the console it return an array that contains only first item from array "selectedWarningStudents", here:
thank you for taking time to help me out, have a good day
Upvotes: 0
Views: 889
Reputation: 17608
Most probably you are getting the studentList
data via an async way. So, since you want to set a state instead of using a derived state, your state can't catch up. Though, in this case, I expect to see no data at all but you can try this:
const [mailList, setMailList] = React.useState([]);
React.useEffect(() => {
var selectedWarningStudents = flattenScoreList(studentList).filter((item) => {
return selected.includes(item._id);
});
setMailList(selectedWarningStudents);
}, [studentList, flattenScoreList, selected]);
But, instead of doing this you can derive the data and use it, maybe with React.useMemo
const selectedWarningStudents = React.useMemo(
() =>
flattenScoreList(studentList).filter((item) => {
return selected.includes(item._id);
}),
[studentList, flattenScoreList, selected]
);
In this case, you don't have any mailList
state, because you are deriving the data from Context data.
By the way, I don't know where do flattenSocreList
and selected
come from, in any case I added them into the dependency arrays. Change it according to your needs.
Here is a working example. As you can see, there is no state in Students
component, you don't need it. You can use studentList
as it is or you can filter it and use this filtered data.
const StudentContext = React.createContext();
const studentData = [
{ id: 1, name: "foo", dep: "aaa" },
{ id: 2, name: "bar", dep: "bbb" },
{ id: 3, name: "baz", dep: "ccc" },
{ id: 4, name: "fizz", dep: "aaa" },
{ id: 5, name: "buzz", dep: "ddd" },
];
function studentApi() {
return new Promise((resolve) => setTimeout(() => resolve(studentData), 1000));
}
function App() {
const [studentList, setStudentList] = React.useState([]);
React.useEffect(() => {
studentApi().then(setStudentList);
}, []);
return (
<StudentContext.Provider value={studentList}>
<div className="App">
<Students />
</div>
</StudentContext.Provider>
);
}
function Students() {
const studentList = React.useContext(StudentContext);
const filteredStudents = React.useMemo(
() => studentList.filter((student) => student.dep === "aaa"),
[studentList]
);
return (
<div>
{filteredStudents.map((student) => (
<div key={student.id}>{student.name} at {student.dep}</div>
))}
</div>
);
}
ReactDOM.render(<App />, document.getElementById("root"));
<script src="https://unpkg.com/react@16/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom@16/umd/react-dom.development.js"></script>
<div id="root" />
Upvotes: 1