React父组件API数据传递给子组件Slide为空问题求助
问题描述
尝试将API数据放入轮播组件,父组件App已成功获取API数据并存入movieObj状态,但传递给子组件Slide后,子组件的slideObj始终是空数组,无法拿到更新后的数据。
App.js代码
import { Component } from 'react' import Header from './components/Header' import Slide from './components/Slide' import Body from './components/Body' import Footer from './components/Footer' import './App.css' import axios from 'axios' export default class App extends Component { constructor(props){ super(props); this.state={ movieObj:[] //用于存储获取到的API数据的状态 } } getMovies=async()=>{ //箭头函数 await axios({ method:'get', url:'/v1/search/movie.json?query="스파이더맨"&display=6', dataType:'json', headers:{ "X-Naver-Client-Id":'pcSk4iqo1SpsvR7nh1Ul', "X-Naver-Client-Secret":'g8wy7q0lQ7' } }) .then(response => { console.log(response); console.log(response.data.items); this.setState({ movieObj:response.data.items }) } ) } componentDidMount(){ this.getMovies()//调用 } render() { console.log(this.state.movieObj) console.log(1) return ( <div id="app"> <Header></Header> <Slide list={this.state.movieObj}></Slide>//将API数据传递给子组件Slide <Body></Body> <Footer></Footer> </div> ) } }
Slide.js代码
import {Component} from 'react'; import { Swiper, SwiperSlide } from 'swiper/react'; import { Navigation, Pagination, Autoplay, A11y } from 'swiper'; import '../css/slide.css' // 导入Swiper样式 import 'swiper/css'; import 'swiper/css/navigation'; import 'swiper/css/pagination'; import 'swiper/css/scrollbar'; export default class Slide extends Component { constructor(props){ super(props); this.state={ slideObj:this.props.list//用于接收来自App.js的(this.props.list)的状态 } } render() { console.log(this.state.slideObj) return ( <Swiper id="slide" modules={[Navigation, Pagination, Autoplay, A11y]} spaceBetween={50} slidesPerView={4} loop= {true} //dir="ltr"//切换轮播前进方向.. navigation// 上一页、下一页按钮 autoplay={{delay: 2000, disableOnInteraction:false}} pagination={{ clickable: true }} onSlideChange={() => console.log('slide change')} onSwiper={(swiper) => console.log(swiper)} > <SwiperSlide className="item"> <div id='movieInfo'> Slide1 </div> </SwiperSlide> <SwiperSlide className="item">Slide 2</SwiperSlide> <SwiperSlide className="item">Slide 3</SwiperSlide> <SwiperSlide className="item">Slide 4</SwiperSlide> <SwiperSlide className="item">Slide 5</SwiperSlide> <SwiperSlide className="item">Slide 6</SwiperSlide> </Swiper> ) } }
解决方案
问题根源:子组件
Slide的slideObj状态是在constructor中通过this.props.list初始化的,但constructor仅在组件挂载时执行一次。父组件的API数据是异步获取的,组件挂载时props.list还是空数组,后续父组件更新movieObj并传递新的props给子组件时,子组件的state不会自动同步更新。解决方法1:直接使用props,不存子组件state
子组件不需要将props存入自身state,直接在render中使用this.props.list即可,这样能实时获取父组件传递的最新数据,同时简化代码:export default class Slide extends Component { render() { console.log(this.props.list) return ( <Swiper id="slide" modules={[Navigation, Pagination, Autoplay, A11y]} spaceBetween={50} slidesPerView={4} loop= {true} navigation autoplay={{delay: 2000, disableOnInteraction:false}} pagination={{ clickable: true }} onSlideChange={() => console.log('slide change')} onSwiper={(swiper) => console.log(swiper)} > {/* 遍历API数据生成轮播项 */} {this.props.list.map((movie, index) => ( <SwiperSlide key={index} className="item"> <div id='movieInfo'> <img src={movie.image} alt={movie.title.replace(/<\/?b>/g, '')} /> <p>{movie.title.replace(/<\/?b>/g, '')}</p> </div> </SwiperSlide> ))} </Swiper> ) } }解决方法2:监听props变化更新子组件state
如果必须将props存入子组件state,需要在componentDidUpdate生命周期中监听props的变化,更新state:export default class Slide extends Component { constructor(props){ super(props); this.state={ slideObj:this.props.list } } componentDidUpdate(prevProps) { // 当props.list变化时,同步更新state if (prevProps.list !== this.props.list) { this.setState({ slideObj: this.props.list }); } } render() { console.log(this.state.slideObj) return ( <Swiper id="slide" modules={[Navigation, Pagination, Autoplay, A11y]} spaceBetween={50} slidesPerView={4} loop= {true} navigation autoplay={{delay: 2000, disableOnInteraction:false}} pagination={{ clickable: true }} onSlideChange={() => console.log('slide change')} onSwiper={(swiper) => console.log(swiper)} > {this.state.slideObj.map((movie, index) => ( <SwiperSlide key={index} className="item"> <div id='movieInfo'> <img src={movie.image} alt={movie.title.replace(/<\/?b>/g, '')} /> <p>{movie.title.replace(/<\/?b>/g, '')}</p> </div> </SwiperSlide> ))} </Swiper> ) } }
内容的提问来源于stack exchange,提问作者MellDaM
相关产品推荐
相关产品推荐

