如何在 <Fragment> React 中使用来自 Promise 的数据
How to use data from a Promise in <Fragment> React
我需要在我的 React 应用程序中获取当前用户的名称,所以我将数据从 action/auth.js 发送到 Navbar.js,在导航栏中我得到了一个 Promise,所以然后我用它来获取数据。我设法 console.log 数据。但是我不能使用它来向用户展示它。
这是我用于发送数据的 auth.js 函数:
export const get_user_data = () => async dispatch => {
if (localStorage.getItem('access')) {
const config = {
headers: {
'Content-Type': 'application/json',
'Authorization': `JWT ${localStorage.getItem('access')}`,
'Accept': 'application/json'
}
};
try {
const res = await axios.get(`${process.env.REACT_APP_API_URL}/auth/users/me/`, config);
let name = res.data.first_name +" "+ res.data.last_name;
return name;
} catch (err) {
return err;
}
} else {
return "else accesss"
}
};
这是我的 Navebar.js 我试图显示数据的地方:
import React, { Fragment } from 'react';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { logout, get_user_data } from '../actions/auth';
const Navbar = ({ get_user_data,logout, isAuthenticated}) => {
console.log("get_user_data", get_user_data().then(res=>{
console.log("res", res)}));
const get_name = () => (
get_user_data().then(res=> {return res})
);
const guestLinks = () => (
<Fragment>
<li className='nav-item'>
<Link className='nav-link' to='/login'>לכניסה</Link>
</li>
<li className='nav-item'>
<Link className='nav-link' to='/signup'>להרשמה</Link>
</li>
</Fragment>
);
const authLinks = () => (
<Fragment>
<li className='nav-item'>
<a className='nav-link' href='#!' onClick={logout}>ליציאה</a>
</li>
<li className='nav-item'>
<Link className='nav-link' to='/homepage'>העסק שלי</Link>
</li>
{<li className='nav-item'>
<Link className='nav-link'>ברוך הבא {get_name()}</Link>
</li>}
</Fragment>
);
return (
<nav className='navbar navbar-expand-lg navbar-light bg-light' lang="he" dir="rtl">
<Link className='navbar-brand' to='/'>החשמלאי</Link>
<button
className='navbar-toggler'
type='button'
data-toggle='collapse'
data-target='#navbarNav'
aria-controls='navbarNav'
aria-expanded='false'
aria-label='Toggle navigation'
>
<span className='navbar-toggler-icon'></span>
</button>
<div className='collapse navbar-collapse' id='navbarNav'>
<ul className='navbar-nav'>
<li className='nav-item active'>
<Link className='nav-link' to='/'>עמוד הבית <span className='sr-only'>(current)</span></Link>
</li>
{isAuthenticated ? authLinks() : guestLinks()}
</ul>
</div>
</nav>
);
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated
});
export default connect(mapStateToProps, { logout, get_user_data })(Navbar);
我使用 get_name() 函数从承诺中解析数据,但我仍然收到承诺错误。
React 错误:
react-dom.development.js:13231 Uncaught Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
谢谢!
我看到你正在使用 redux 和 connect 连接到你的状态。
如果您在此之前使用过 hooks 可能会更短更清晰:
const Navbar = () => {
const dispatch = useDispatch()
// Instead of using connect to get state, you can use the hook useSelector:
const isAuthenticated = useSelector(state => state.auth.isAuthenticated);
// No user to begin with
const [user, setUser] = useState(null);
// This will run once when the navbar renders for the first time
useEffect(() => {
get_user_data().then(fetchedUser => setUser(fetchedUser))
}, [])
function dispatchSomeAction() {
// Fire of action to redux
dispatch({ type: "logout" })
}
return (
<Fragment>
{user !== null && (<div>{user.name}</div>)}
<div>{isAuthenticated ? <p>Authenticated!</p> : <p>Not Authenticated</p>}</div>
<button onClick={dispatchSomeAction} >I will dispatch a action to redux</button>
</Fragment>
);
};
如果您使用的是 redux,还请阅读 redux-thunk。它允许您执行异步操作,例如 API 调用并将返回值存储在您的状态中 :)
分析
您的行为是因为您试图显示 Promise
。在显示之前,您需要等待 Promise
被解析。在这里,我将使用 useState
和 useEffect
挂钩来实现我所说的行为。
解决方案
首先,您需要一个状态来保持您的 userData
。从您在 get_user_data
函数中的代码,我们假设我们正在谈论的 data
是用户名。此状态的默认值为空字符串。
const [name, setName] = useState('');
然后,我将创建一个 useEffect
挂钩以使用您的 get_user_data
函数填充新创建的 name
状态:
useEffect(() => {
get_user_data().then((data) => {
setName(data);
});
}, []);
此挂钩将获取数据并在获取完成后设置 name
状态。
然后我们需要在任何需要的地方使用这个 name
状态。该组件的行为是当我们获取用户名时它会显示 ''
,但是一旦数据可用,UI 就会显示它。把它们放在一起,我们有:
import React, { Fragment, useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { logout, get_user_data } from '../actions/auth';
const Navbar = ({ get_user_data,logout, isAuthenticated}) => {
const [name, setName] = useState('');
useEffect(() => {
get_user_data().then((data) => {
setName(data);
});
}, []);
const guestLinks = () => (
<Fragment>
<li className='nav-item'>
<Link className='nav-link' to='/login'>לכניסה</Link>
</li>
<li className='nav-item'>
<Link className='nav-link' to='/signup'>להרשמה</Link>
</li>
</Fragment>
);
const authLinks = () => (
<Fragment>
<li className='nav-item'>
<a className='nav-link' href='#!' onClick={logout}>ליציאה</a>
</li>
<li className='nav-item'>
<Link className='nav-link' to='/homepage'>העסק שלי</Link>
</li>
{<li className='nav-item'>
<Link className='nav-link'>ברוך הבא {get_name()}</Link>
</li>}
</Fragment>
);
return (
<nav className='navbar navbar-expand-lg navbar-light bg-light' lang="he" dir="rtl">
<Link className='navbar-brand' to='/'>החשמלאי</Link>
<button
className='navbar-toggler'
type='button'
data-toggle='collapse'
data-target='#navbarNav'
aria-controls='navbarNav'
aria-expanded='false'
aria-label='Toggle navigation'
>
<span className='navbar-toggler-icon'></span>
</button>
<div className='collapse navbar-collapse' id='navbarNav'>
<ul className='navbar-nav'>
<li className='nav-item active'>
<Link className='nav-link' to='/'>עמוד הבית <span className='sr-only'>(current)</span></Link>
</li>
{isAuthenticated ? authLinks() : guestLinks()}
</ul>
</div>
</nav>
);
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated
});
export default connect(mapStateToProps, { logout, get_user_data })(Navbar);
我需要在我的 React 应用程序中获取当前用户的名称,所以我将数据从 action/auth.js 发送到 Navbar.js,在导航栏中我得到了一个 Promise,所以然后我用它来获取数据。我设法 console.log 数据。但是我不能使用它来向用户展示它。 这是我用于发送数据的 auth.js 函数:
export const get_user_data = () => async dispatch => {
if (localStorage.getItem('access')) {
const config = {
headers: {
'Content-Type': 'application/json',
'Authorization': `JWT ${localStorage.getItem('access')}`,
'Accept': 'application/json'
}
};
try {
const res = await axios.get(`${process.env.REACT_APP_API_URL}/auth/users/me/`, config);
let name = res.data.first_name +" "+ res.data.last_name;
return name;
} catch (err) {
return err;
}
} else {
return "else accesss"
}
};
这是我的 Navebar.js 我试图显示数据的地方:
import React, { Fragment } from 'react';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { logout, get_user_data } from '../actions/auth';
const Navbar = ({ get_user_data,logout, isAuthenticated}) => {
console.log("get_user_data", get_user_data().then(res=>{
console.log("res", res)}));
const get_name = () => (
get_user_data().then(res=> {return res})
);
const guestLinks = () => (
<Fragment>
<li className='nav-item'>
<Link className='nav-link' to='/login'>לכניסה</Link>
</li>
<li className='nav-item'>
<Link className='nav-link' to='/signup'>להרשמה</Link>
</li>
</Fragment>
);
const authLinks = () => (
<Fragment>
<li className='nav-item'>
<a className='nav-link' href='#!' onClick={logout}>ליציאה</a>
</li>
<li className='nav-item'>
<Link className='nav-link' to='/homepage'>העסק שלי</Link>
</li>
{<li className='nav-item'>
<Link className='nav-link'>ברוך הבא {get_name()}</Link>
</li>}
</Fragment>
);
return (
<nav className='navbar navbar-expand-lg navbar-light bg-light' lang="he" dir="rtl">
<Link className='navbar-brand' to='/'>החשמלאי</Link>
<button
className='navbar-toggler'
type='button'
data-toggle='collapse'
data-target='#navbarNav'
aria-controls='navbarNav'
aria-expanded='false'
aria-label='Toggle navigation'
>
<span className='navbar-toggler-icon'></span>
</button>
<div className='collapse navbar-collapse' id='navbarNav'>
<ul className='navbar-nav'>
<li className='nav-item active'>
<Link className='nav-link' to='/'>עמוד הבית <span className='sr-only'>(current)</span></Link>
</li>
{isAuthenticated ? authLinks() : guestLinks()}
</ul>
</div>
</nav>
);
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated
});
export default connect(mapStateToProps, { logout, get_user_data })(Navbar);
我使用 get_name() 函数从承诺中解析数据,但我仍然收到承诺错误。
React 错误:
react-dom.development.js:13231 Uncaught Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead.
谢谢!
我看到你正在使用 redux 和 connect 连接到你的状态。 如果您在此之前使用过 hooks 可能会更短更清晰:
const Navbar = () => {
const dispatch = useDispatch()
// Instead of using connect to get state, you can use the hook useSelector:
const isAuthenticated = useSelector(state => state.auth.isAuthenticated);
// No user to begin with
const [user, setUser] = useState(null);
// This will run once when the navbar renders for the first time
useEffect(() => {
get_user_data().then(fetchedUser => setUser(fetchedUser))
}, [])
function dispatchSomeAction() {
// Fire of action to redux
dispatch({ type: "logout" })
}
return (
<Fragment>
{user !== null && (<div>{user.name}</div>)}
<div>{isAuthenticated ? <p>Authenticated!</p> : <p>Not Authenticated</p>}</div>
<button onClick={dispatchSomeAction} >I will dispatch a action to redux</button>
</Fragment>
);
};
如果您使用的是 redux,还请阅读 redux-thunk。它允许您执行异步操作,例如 API 调用并将返回值存储在您的状态中 :)
分析
您的行为是因为您试图显示 Promise
。在显示之前,您需要等待 Promise
被解析。在这里,我将使用 useState
和 useEffect
挂钩来实现我所说的行为。
解决方案
首先,您需要一个状态来保持您的 userData
。从您在 get_user_data
函数中的代码,我们假设我们正在谈论的 data
是用户名。此状态的默认值为空字符串。
const [name, setName] = useState('');
然后,我将创建一个 useEffect
挂钩以使用您的 get_user_data
函数填充新创建的 name
状态:
useEffect(() => {
get_user_data().then((data) => {
setName(data);
});
}, []);
此挂钩将获取数据并在获取完成后设置 name
状态。
然后我们需要在任何需要的地方使用这个 name
状态。该组件的行为是当我们获取用户名时它会显示 ''
,但是一旦数据可用,UI 就会显示它。把它们放在一起,我们有:
import React, { Fragment, useState, useEffect } from 'react';
import { Link } from 'react-router-dom';
import { connect } from 'react-redux';
import { logout, get_user_data } from '../actions/auth';
const Navbar = ({ get_user_data,logout, isAuthenticated}) => {
const [name, setName] = useState('');
useEffect(() => {
get_user_data().then((data) => {
setName(data);
});
}, []);
const guestLinks = () => (
<Fragment>
<li className='nav-item'>
<Link className='nav-link' to='/login'>לכניסה</Link>
</li>
<li className='nav-item'>
<Link className='nav-link' to='/signup'>להרשמה</Link>
</li>
</Fragment>
);
const authLinks = () => (
<Fragment>
<li className='nav-item'>
<a className='nav-link' href='#!' onClick={logout}>ליציאה</a>
</li>
<li className='nav-item'>
<Link className='nav-link' to='/homepage'>העסק שלי</Link>
</li>
{<li className='nav-item'>
<Link className='nav-link'>ברוך הבא {get_name()}</Link>
</li>}
</Fragment>
);
return (
<nav className='navbar navbar-expand-lg navbar-light bg-light' lang="he" dir="rtl">
<Link className='navbar-brand' to='/'>החשמלאי</Link>
<button
className='navbar-toggler'
type='button'
data-toggle='collapse'
data-target='#navbarNav'
aria-controls='navbarNav'
aria-expanded='false'
aria-label='Toggle navigation'
>
<span className='navbar-toggler-icon'></span>
</button>
<div className='collapse navbar-collapse' id='navbarNav'>
<ul className='navbar-nav'>
<li className='nav-item active'>
<Link className='nav-link' to='/'>עמוד הבית <span className='sr-only'>(current)</span></Link>
</li>
{isAuthenticated ? authLinks() : guestLinks()}
</ul>
</div>
</nav>
);
};
const mapStateToProps = state => ({
isAuthenticated: state.auth.isAuthenticated
});
export default connect(mapStateToProps, { logout, get_user_data })(Navbar);