React Native使用Hooks获取数据需三次刷新才显示到日历组件如何解决
问题原因
- React的setState为异步更新,你调用
setStartDate、setEndDate后立刻读取对应state值,拿到的仍是更新前的旧值,只有组件重渲染后state才会更新。你多次按Ctrl+S触发热重载的过程刚好让state完成了多轮更新,才会显示正确结果。 - 用forEach循环调用
setStartDate、setEndDate的写法错误,多次调用setState会触发无效重渲染,且最终state只会保留数组最后一个元素的值,无法拿到所有起止日期对。 - 如果你代码里的
dateArray、newDaysObject是组件内的普通变量而非通过useState声明的响应式状态,修改它们不会触发组件重渲染,日历组件无法感知到数据变化。
修复方案
- 首先声明用于传给日历组件的响应式高亮日期状态:
// 该状态直接对应react-native-calendar的markedDates属性 const [markedDates, setMarkedDates] = useState({})
- 修正异步请求逻辑,直接用接口返回的原始数据计算所有需要高亮的日期,不要用state做中转:
const myConstrucion = async () => { try { let user_id = await AsyncStorage.getItem('user_id'); const _id = user_id; let res = await axios.get(`https://myseenapp.herokuapp.com/constructionSite/${_id}`); let data = res.data; setConstruction(data); const newMarked = {} // 遍历所有施工项目,逐个计算每个项目的日期范围 data.forEach(item => { // 直接用当前项的起止日期处理,不需要存state中转 const start = moment(item.startDate.split("-").reverse().join("-")) const end = moment(item.endDate.split("-").reverse().join("-")) let currentDay = start.clone() // 生成当前起止范围内的所有日期配置 while (currentDay.isSameOrBefore(end)) { const dateStr = currentDay.format("YYYY-MM-DD") newMarked[dateStr] = { textColor: "white", color: 'gold', selected: true, } currentDay.add(1, 'days') } }) // 一次性更新高亮日期状态,触发组件重渲染 setMarkedDates(newMarked) } catch (err) { console.log(err) } };
- useEffect保持原有逻辑即可,最后将
markedDates传给react-native-calendar组件的markedDates属性。
注意事项
如果startDate、endDate在其他业务场景需要使用,不要用循环调用setState的方式存储,应该声明数组类型的state批量存储所有起止日期对。
内容的提问来源于stack exchange,提问作者manon_ab
相关产品推荐
相关产品推荐

