React展示API返回JSON中retDonnees嵌套对象的问题求助
解决React展示API返回的retDonnees数据问题
我看了你的代码,问题主要出在数据层级的访问和组件props传递上,还有几个小拼写错误,咱们一步步来修正:
核心问题拆解
- API返回的是数组结构,第一个对象里包含
retEntete和retDonnees两层,但你在setState时直接把data[0]赋值给了test,导致在DisplayTest里直接访问test.constat是找不到的——它实际藏在test.retDonnees.constat里。 - App组件render里给
DisplayTest传的recupTest根本没定义,应该传递this.state.test.retDonnees,而且得处理初始加载时数据未返回的空值情况,避免报错。 DisplayTest里的按钮有拼写错误:把法语的reponse写成了英语的response,导致选项渲染不出来。
具体修改步骤
1. 修正App组件的state更新逻辑
在getTest的异步回调里,直接把API返回的retDonnees层级赋值给state的test,这样后续访问更直接:
.then(data => { console.log(data) this.setState({ test: data[0].retDonnees }); // 跳过外层,直接取retDonnees });
然后在render里,把正确的state数据传给DisplayTest:
<DisplayTest test={this.state.test} />
2. 修复DisplayTest的拼写错误
把按钮里的test.response1、test.response3改成test.reponse1、test.reponse3:
<MDBBtn>{test.reponse1}</MDBBtn> <MDBBtn>{test.reponse2}</MDBBtn> <MDBBtn>{test.reponse3}</MDBBtn> <MDBBtn>{test.reponse4}</MDBBtn>
3. 添加空值保护(推荐)
因为API请求是异步的,初始渲染时test还是初始的空对象,所以可以在DisplayTest里加个加载提示,或者用可选链避免报错:
const DisplayTest = ({test}) => { if (!test.constat) return <div>正在加载测试内容...</div>; return ( // 原组件内容 ); }
修改后的完整代码
App.js
const afficheInit = { constat: null, instruction: null } const appInit = { appMode: "evaluation", appEtape: "init1" } class App extends Component { constructor(props) { super(props); this.state = { test: afficheInit, envEntete: appInit, retEntete: null }; } componentDidMount() { this.getTest(this.state); } getTest(param) { fetch("an API", { method: 'POST', headers: { 'Accept': 'application/json', 'Content-Type': 'text/plain' }, body: JSON.stringify(param), }) .then(response => response.json()) .then(data => { console.log(data) this.setState({ test: data[0].retDonnees }); }); } render() { const mode = "Evaluation"; // 这里假设你有定义mode变量,按需调整 if (mode === "Evaluation") { return ( <MDBCol> <MDBCard> <MDBCardImage className="img-fluid" src="https://mdbootstrap.com/img/Photos/Others/images/43.jpg" waves /> <MDBCardBody> <DisplayTest test={this.state.test} /> <GenerateTest selectTest={() => this.getTest()} /> </MDBCardBody> </MDBCard> </MDBCol> ); } else { return ( <MDBCol> <MDBCard> <MDBCardImage className="img-fluid" src="https://mdbootstrap.com/img/Photos/Others/images/43.jpg" waves /> <MDBCardBody> <MDBCardTitle>???</MDBCardTitle> <MDBCardText> Oh! </MDBCardText> <MDBBtn href="#">Hey !</MDBBtn> </MDBCardBody> </MDBCard> </MDBCol> ); } } } export default App;
DisplayTest.jsx
const DisplayTest = ({test}) => { if (!test.constat) return <div>正在加载测试内容...</div>; return ( <div className="DisplayTest"> <p className='superclasse'> {test.constat} </p> <MDBCardTitle className= 'super'>{test.instruction}</MDBCardTitle> <MDBCardText> {test.question1}</MDBCardText> <MDBCardText> {test.question2}</MDBCardText> <MDBCardText> {test.question3}</MDBCardText> <MDBBtn>{test.reponse1}</MDBBtn> <MDBBtn>{test.reponse2}</MDBBtn> <MDBBtn>{test.reponse3}</MDBBtn> <MDBBtn>{test.reponse4}</MDBBtn> </div> ); } export default DisplayTest;
进阶:用Object.keys.map动态渲染内容
如果你想让组件更灵活(比如以后增加question/reponse字段不用改代码),可以用Object.keys配合map动态渲染:
const DisplayTest = ({test}) => { if (!test) return <div>加载中...</div>; // 过滤出所有question开头的字段 const questions = Object.entries(test).filter(([key]) => key.startsWith('question')); // 过滤出所有非正确答案的reponse字段 const reponses = Object.entries(test).filter(([key]) => key.startsWith('reponse') && !key.includes('correcte')); return ( <div className="DisplayTest"> <p className='superclasse'> {test.constat} </p> <MDBCardTitle className= 'super'>{test.instruction}</MDBCardTitle> {/* 动态渲染问题 */} {questions.map(([key, value]) => ( <MDBCardText key={key}>{value}</MDBCardText> ))} {/* 动态渲染选项按钮 */} {reponses.map(([key, value]) => ( <MDBBtn key={key}>{value}</MDBBtn> ))} </div> ); }
内容的提问来源于stack exchange,提问作者Marion
相关产品推荐
相关产品推荐

