React中打印对象字段存在,但访问属性返回undefined的原因?
问题描述
我有一个幸存者列表:
const survivorsList = [ { id: 1, name: "Ace Visconti", image_path: "static/survivors/ace_visconti.jpg", }, { id: 2, name: "Vittorio Toscano", image_path: "static/survivors/vittorio_toscano.jpg", }, { id: 3, name: "Nancy Wheeler", image_path: "static/survivors/nancy_wheeler.jpg", }, { id: 4, name: "Claudette Morel", image_path: "static/survivors/claudette_morel.jpg", }, ];
在React应用的渲染函数中尝试访问该列表:
renderSurvivorName = () => { const randomSurvivor = this.state.survivorsList.filter( (survivor) => survivor.name === "Ace Visconti" ); console.log("Random Survivor: " + JSON.stringify(randomSurvivor)) console.log("Survivor Name: " + randomSurvivor.name); // return randomSurvivor['name']; return randomSurvivor.name; };
控制台输出如下:
Random Survivor: [{"id":1,"name":"AceVisconti","image_path":"static/survivors/ace_visconti.jpg"}]. App.js:62 Survivor Name: undefined. App.js:63
我尝试过点语法和方括号语法访问属性,均返回undefined。怀疑是两次调用间作用域变化或页面重载导致值未设置?查阅过StackOverflow文章,但因未进行API调用,认为无需使用async,这个想法是否错误?
完整React代码
import React, { Component } from "react"; const survivorsList = [ { id: 1, name: "Ace Visconti", image_path: "static/survivors/ace_visconti.jpg", }, { id: 2, name: "Vittorio Toscano", image_path: "static/survivors/vittorio_toscano.jpg", }, { id: 3, name: "Nancy Wheeler", image_path: "static/survivors/nancy_wheeler.jpg", }, { id: 4, name: "Claudette Morel", image_path: "static/survivors/claudette_morel.jpg", }, ]; class App extends Component { constructor(props) { super(props); this.state = { survivorsList: survivorsList, survivorName: "Ace Visconti" }; } // displayRandom = (status) => { // if (status) { // return this.setState({ randomCalculated: true }); // } // // return this.setState({ randomCalculated: false }); // }; renderSurvivorTitle = () => { return ( <div className="nav nav-tabs"> <span className={this.state.randomCalculated ? "nav-link active" : "nav-link"} onClick={() => this.displayRandom(true)} > Survivor </span> </div> ); }; renderSurvivorName = () => { const randomSurvivor = this.state.survivorsList.filter( (survivor) => survivor.name === "Ace Visconti" ); console.log("Random Survivor: " + JSON.stringify(randomSurvivor)) console.log("Survivor Name: " + randomSurvivor.name); // return randomSurvivor['name']; return <div>Survivor: {this.state.survivorName}</div>; }; render() { return ( <main className="container"> <h1 className="text-white text-uppercase text-center my-4">Todo app</h1> <div className="row"> <div className="col-md-6 col-sm-10 mx-auto p-0"> <div className="card p-3"> <div className="mb-4"> <button className="btn btn-primary" > Select Random Survivor </button> </div> <div>{this.renderSurvivorTitle()}</div> <div>{this.renderSurvivorName()}</div> {/*<div>{"Ace Visconti"}</div>*/} </div> </div> </div> </main> ); } } export default App;
package.json
{ "name": "dbd-randomizer-ui", "version": "0.1.0", "private": true, "dependencies": { "@testing-library/jest-dom": "latest", "@testing-library/react": "latest", "@testing-library/user-event": "latest", "react": "latest", "react-dom": "latest", "react-scripts": "latest", "web-vitals": "latest", "bootstrap": "latest", "reactstrap": "latest" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject" }, "eslintConfig": { "extends": [ "react-app", "react-app/jest" ] }, "browserslist": { "production": [ ">0.2%", "not dead", "not op_mini all" ], "development": [ "last 1 chrome version", "last 1 firefox version", "last 1 safari version" ] } }
问题原因与解决方法
核心问题
你使用的filter方法返回的是符合条件的元素组成的数组,而非单个对象。所以randomSurvivor是一个数组,数组本身没有name属性,自然返回undefined。从控制台输出也能看出结果被包裹在数组中:Random Survivor: [{"id":1,...}]。
解决步骤
- 替换
filter为find:如果要查找单个匹配元素,使用find方法,它会返回第一个符合条件的对象,而非数组:
const randomSurvivor = this.state.survivorsList.find( (survivor) => survivor.name === "Ace Visconti" );
- 处理空值情况:如果没有找到匹配元素,
find会返回undefined,访问属性前建议做判断避免报错:
console.log("Survivor Name: " + (randomSurvivor?.name || "未找到幸存者")); return <div>Survivor: {randomSurvivor?.name || "未找到幸存者"}</div>;
- 关于
async的疑问:你的判断正确,这里没有异步操作(如API请求),完全不需要使用async/await,问题与异步无关。
额外修复点
- 当前
renderSurvivorName最终返回的是this.state.survivorName,和查找逻辑无关,若要显示查找结果,需改为返回randomSurvivor?.name。 renderSurvivorTitle中用到了this.state.randomCalculated,但state未初始化该值,会导致报错,建议在constructor中补充:
this.state = { survivorsList: survivorsList, survivorName: "Ace Visconti", randomCalculated: false // 初始化状态 };
同时取消displayRandom方法的注释,否则点击事件会报错。
内容的提问来源于stack exchange,提问作者CryptoRAT
相关产品推荐
相关产品推荐

