Reputation: 1380
I'm new on React and I have a problem in this code:
class Tests extends React.Component {
async getTests() {
var url = "http://127.0.0.1:100/getTestList"
var buttons=[];
const resp = await fetch(url);
const data = await resp.json();
for(let pkg in data){
console.log(pkg);
for (let cls in data[pkg]){
console.log(cls);
for (var i = 0; i < data[pkg][cls].length; i++) {
let m= data[pkg][cls][i];
buttons.push(<button value={cls}>{m}</button>);
}
}
}
return buttons;
}
render(){
return(
<div>
<h4>Using .map()</h4>
{this.getTests()}
</div>
)
}
}//fine classe
// ========================================
ReactDOM.render(
<Tests />,
document.getElementById('root')
);
I take correctly JSON Response from POST service, iterate correctly the JSON for to have an array of buttons with value and text but I have this error on Chrome:
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. in div (at src/index.js:95) in Tests (at src/index.js:108)
Some Tips? Thanks Regards
Upvotes: 0
Views: 1490
Reputation: 214
this error is expected. From your code, getTest method returns an array of buttons. You cannot render an array or an object from a react component.
Instead you can
Upvotes: -1
Reputation: 10579
getTests()
is an async function and it will always return a promise object. React is complaining because you are passing a promise object to the render method.
You could store the api response in a state, and set the state in getTests
method. React will update the ui
on state update.
Few changes in the code.
getTests()
in componentDidMount
method.Example:
class Tests extends React.Component {
constructor(props) {
super(props);
this.state = {
buttons: []
}
}
async getTests() {
var url = "http://127.0.0.1:100/getTestList"
var buttons = [];
const resp = await fetch(url);
const data = await resp.json();
for (let pkg in data) {
console.log(pkg);
for (let cls in data[pkg]) {
console.log(cls);
for (var i = 0; i < data[pkg][cls].length; i++) {
let m = data[pkg][cls][i];
buttons.push({ value: cls, displayName: m });
}
}
}
this.setState( () => {
return {
buttons
}
});
}
async componentDidMount() {
await getTests();
}
render() {
return (
<div>
<h4>Using .map()</h4>
{this.state.buttons.map(button => <button key={button.value} value={button.value}>{button.displayName}</button>) }
</div>
)
}
}//fine classe
// ========================================
ReactDOM.render(
<Tests />,
document.getElementById('root')
);
Or you could use a functional component for this.
const ButtonGroup = () => {
const [buttons, setButtons] = useState([]);
useEffect(() => {
await getTests();
}, []);
async function getTests() {
const url = 'http://127.0.0.1:100/getTestList';
const resp = await fetch(url);
const data = await resp.json();
const buttonData = [];
for (let pkg in data) {
for (let cls in data[pkg]) {
for (var i = 0; i < data[pkg][cls].length; i++) {
let m = data[pkg][cls][i];
buttonData.push({ value: cls, displayName: m });
}
}
}
setButtons(buttonData);
}
return (
<div>
<h4>Using.map()</h4>
{buttons.map(button =>
(
<button key={button.value} value={button.value}>{button.displayName}</button>
)
)}
</div>
);
}
export default ButtonGroup;
Upvotes: 1
Reputation: 15166
I would use a function component with useState
and useEffect
for this case. In useEffect
you can fetch your data from the endpoint then using .map()
you can represent your buttons from the array what you instantiate with useState
.
Please see the following solution which might resolve the issue:
const Tests = () => {
const [buttons, setButtons] = useState([]);
useEffect(() => {
async getTests() {
const url = 'http://127.0.0.1:100/getTestList';
const resp = await fetch(url);
const data = await resp.json();
const fetchedButtons = [];
for (let pkg in data) {
for (let cls in data[pkg]) {
for (var i = 0; i < data[pkg][cls].length; i++) {
let m = data[pkg][cls][i];
fetchedButtons.push(<button value={cls}>{m}</button>);
}
}
}
setButtons(fetchedButtons);
}
getTests();
}, []);
return <div>
<h4>Using.map()</h4>
{/* here mapping the buttons array */}
{
buttons && buttons.map(e => e);
}
</div>
}
I hope this helps!
Upvotes: 1