简体   繁体   中英

Render Items from useState Hook React

I have made a call to my api using useEffect and stored the array of items using useState hook but I'm finding it difficult to render those items into a custom component which will also have the data passed.

Here's my react snippets:

export default function CreateCast() {

 const [open, setOpen] = useState(false);
 const [bibleCastItems, setBibleCastItems] = useState([]);

 const classes = useStyles();

 const fabStyle = {
   bottom: 50.0,
   right: 30.0,
   position: "fixed"
 };

 useEffect(()=>{
   async function fetchData(){
    var items = await APIService.getAllBibleCasts();
    // console.log(items);
    // console.log(items.data.bibleCasts);
    setBibleCastItems([items.data.bibleCasts]); 
    // items.data.bibleCasts.length > 0 ? setBibleCastItems([items.data.bibleCasts]) 
    // : setBibleCastItems([]);
  }
  fetchData();
  }, []
);

// console.log('bibleCastItems length ' + bibleCastItems.length);

return (
  <GridContainer>
    <GridItem xs={12} sm={12} md={12}>
      <Card plain>
        <CardHeader plain color="primary">
         <div className={classes.container}>
           <div className={classes.left}>
           <h4 className={classes.cardTitleWhite}>All BibleCasts</h4>
           <p className={classes.cardCategoryWhite}>
             Powered by our friends from <b>Unicorn Tech Consultants</b>{" "}
           </p>
         </div>
        </div>
       </CardHeader>
       <CardBody>
         {
           bibleCastItems.map((item, index) => <CastItem key={index} bibleCast={item[index]}/>) // this is where I'm facing issue
           // bibleCastItems.map((item, index) => {
            // console.log(item);
            // setMyItem(item);
            // return <div key={index}>{index}</div>
          // })
        }
        <div className={classes.right}>
            <Fab style={fabStyle} onClick={handleClickOpen}>
              <AddIcon />
            </Fab>
            <UploadFormDialog 
              open={open}
              handleClose={handleClose}
            />
        </div>           
      </CardBody>
    </Card>
  </GridItem>
 </GridContainer>
);

function handleClickOpen(){
  setOpen(true);
};

function handleClose(){
  setOpen(false);
};

}

Here's my state from browser view: [![state view][1]][1]

How do I map this state to be a list of components? I'm confused about it

As you can see, I'm using a dialog to create new items and close the dialog once the request is successful. I have one doubt here, how do I tell the main component hosting the dialog that the new data has been fetched and should be added to the state?

My main question here is how to map the items in state to return a list of <CastItem /> component

CastItem Component Snippet

export default function CastItem(props) {

let {bibleCast} = props;

const classes = useStyles();

return <GridContainer>
    <GridItem xs={12} sm={6} md={4}>
        <Card>
            <CardHeader color="info" stats icon>
                <CardIcon color="info">
                    <Streams />
                </CardIcon>
            </CardHeader>

            <CardBody>
                <h3 className={classes.cardTitle}>{bibleCast.title}</h3>
                <p className={classes.cardCategory}> Reinhard Bonnke</p>
            </CardBody>
        </Card>
    </GridItem>
</GridContainer>
}

CastItem.propTypes = {
  bibleCast: PropTypes.object.isRequired,
}

JSON Response from API in console:

[![json response][2]][2]

If you were to create a state variable to represent this response as a list and display that list, how would you go about it, using hooks. Thank you. [1]: https://i.stack.imgur.com/QkthN.png [2]: https://i.stack.imgur.com/8Hf11.png

Mistake you are doing is in CreateCast component, form api you are already getting an array again you are passing it inside an array, so it is coming as nested array

Do like this

useEffect(()=>{
   async function fetchData(){
    var items = await APIService.getAllBibleCasts();
    setBibleCastItems(items.data.bibleCasts); 
  }
  fetchData();
  }, []
);


For Maping do like this


{
           bibleCastItems.map((item, index) => <CastItem key={index} bibleCast={item}/>) 
        }

// For question how to update parent from child follow below

There are two ways you can set data in a parent component, one is refetch from the api or pass from children to parent and update the state there

I have an example here how to update parent and children,to add names to a list,name list state is maintained in parent component here and child will pass back value to parent by adding name

import { useState } from "react";
import Child from "./Child";

export default function Parent() {
  const [list, setList] = useState(["ram"]);

  const handleAddName = (name) => {
    if (name) {
      setList([name, ...list]);
  // or you can refetch the list from api here

    }
  };
  return (
    <div>
      <div style={{ float: "left" }}>
        <h1>I am a parent Component</h1>
        <ul>
          {list &&
            list.map((item) => {
              return <li key={item}>{item}</li>;
            })}
        </ul>
      </div>

      <Child handleSubmit={handleAddName} />
    </div>
  );
}

Child


import { useState } from "react";

export default function Child(props) {
  const [name, setName] = useState("");

  const updateNameList = (name) => {
    if (name) {
      props.handleSubmit(name);
      //reset field after data is sent
      // you can also save data here making post request respective api
      setName("");

    }
  };

  return (
    <div style={{ float: "right" }}>
      <h1>I am a Child Component</h1>
      <p> Add names below</p>
      <br />
      <input value={name} onChange={(e) => setName(e.target.value)} />
      <button onClick={() => updateNameList(name)}>Add</button>
    </div>
  );
}

refer to this codesand box

编辑顽皮-hugle-bdt7k

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM