I'm trying to display all the minted tokens on the front page of my dapp, so I created an array in solidity and pushed the tokenId to it, then tried using a spread operator, and mapping it to the tokenURI's. Unfortunately, I haven't been able to get the image to display it.
for (let i = 1; i <= totalSupply; i++) { //this is listing an array of minted tokens
const tokenURI = await contract.methods.tokenURI(i - 1).call()
const imageURI = await tokenURI.image
// how should we handle the state on the front end
this.setState({
NFTz: [...this.state.NFTz, imageURI] // spread operator
}) // pretty sure the array could be done on the front end
}
console.log(this.state.imageURI)
console.log(this.state.NFTz)
The console returns:
index.js:1437 Warning: Each child in a list should have a unique "key" prop.
Check the render method of `App`. See fb.me/react-warning-keys for more information.
in div (at App.js:136)
in App (at src/index.js:7)
It's rendered it onto MDBcards with:
<div className="row textCenter">
{this.state.NFTz.map((key, imageURI) => {
return (
<div>
<div>
<MDBCard className="token img" style={{ maxWidth: '22rem' }}>
<MDBCardImage src={imageURI} position='top' height='250rem' style={{ marginRight: '4px' }} />
<MDBCardBody>
<MDBCardTitle></MDBCardTitle>
<MDBCardText></MDBCardText>
<MDBBtn href={imageURI}>Download</MDBBtn>
</MDBCardBody>
</MDBCard>
</div>
</div>
PS: Err, probably more efficient to create an array on the front end, instead of in solidity.
Thank you and God Bless
Related
I have a function where a user types in there sitemap and it returns all the links in there sitemap.
How can I then save all of those links in individual documents in a specific collection on Firebase?
See below for the current firebase set function. Erro returns "Function DocumentReference.set() called with invalid data. Data must be an object, "
const saveAllCrawl = async () => {
await db.collection('urls').doc('test').set(urls);
}
Current map of the array the sitemap crawler returns & Scrap Sitemap function
const scrapeSitemap = async (e) => {
e.preventDefault();
console.log(sitemapURL)
const array = await GetSitemapLinks(sitemapURL);
setURLS(array)
}
{urls && urls.map((user) => (
<Grid container spacing={0} >
<Grid xs={6} sm={6} md={6}>
<li className="user">{user}</li>
</Grid>
</Grid>
))}
<Button onClick={saveAllCrawl}>Save All To Firebase</Button>
In document every value is being stored against a key.
Like if there are multiple urls and you want to store each in a separate document so you have to stored them against any key.
Collections: URLS
Document Id : (generated_key)
Document Data :
{ "key" : "url_value" }
So, as mentioned above for this you have to create a batch in which you assign all queries to a batch and after that set batch.commit().
Now, if you are trying to store them in a list like an array.
{
"urls": [
"url_one",
"url_one"
]
}
So, first create an object and assigned all string values to key and then set that to a document.
I have a component that renders an array with .map() and a button that setState the shuffled version of it.
I'm trying to have it update every time I click that button but it doesn't.
const Home: NextPage = () => {
const [random, setRandom] = useState(students);
function randomize() {
const shuffle = students.sort(() => 0.5 - Math.random());
setRandom(shuffle);
}
return (
<>
<main className="container mx-auto flex min-h-screen flex-col items-center justify-center p-4">
<h1 className="text-6xl font-bold">This week's seat</h1>
<button onClick={randomize}>Shuffle</button>
{/* Seatings */}
<div className="seatbox">
{random.map((student) => (
<Seat key={student}>{student}</Seat>
))}
</div>
</main>
</>
);
};
I tried to log the random state, it got updated it just doesn't get rendered probably.
The Seat component is made with styled-components and the students array is an array of strings with the students name like this
const students = [
"Joe",
"Jason"
]
This sorts the array:
const shuffle = students.sort(() => 0.5 - Math.random());
But... it sorts the array in place and returns a reference to that same array. Since the reference equality hasn't changed (an array is a kind of object after all), React has no way to know that the state has been updated. It doesn't do any kind of deep compare, just an equality comparison for whatever is sent to it.
If you duplicate the array just before sorting (so as to not mutate it), the newly sorted array will be a new object reference and won't be "equal" to the previous state:
const shuffle = [...students].sort(() => 0.5 - Math.random());
I have a gallery that displays a number of books per row. This gallery takes an array of books as a prop and uses "itemsPerRow" prop to chunk the books into a 2 dimensional array and then loops through all the books to display the books in a grid-like structure.
export default function Gallery({ items, itemsPerRow, renderLink }) {
itemsPerRow = itemsPerRow ?? 3
const rows = chunk(items, itemsPerRow)
const renderEmptyItems = (itemsToRender) => {
const items = []
for(let n = itemsToRender; n > 0; n--) {
items.push(<GalleryItem key={`empty_${n}`} empty/>)
}
return items
}
return (
<div>
{
rows.map((row, index) => (
<div key={index} className="tile is-ancestor">
{row.map(item => <GalleryItem key={item.id} renderLink={renderLink} {...item}/>)}
{/* Add empty gallery items to make rows even */}
{index + 1 === rows.length && renderEmptyItems(itemsPerRow - row.length)}
</div>
))
}
</div>
)
}
However, unless I give each div representing a row a key, react complains about the lack of keys. As I understand it, using the index as a key doesn't really help react and should be avoided. So what should I use as a key here <div key={index} className="tile is-ancestor"> instead of the index?
Use a unique identifier (book.id, maybe book.title if it's unique) for the key props. If your data does not have a unique identifier, it's okay to use index.
You need to specify a value that uniquely identify the item, such as the id. You can read more about keys in the documentation.
Also it is not recommended to use indexes as keys if the order of your data can change, as React relies on the keys to know which components to re-render, the documentation I linked explains that further.
You can use the unique_identifier which differentiate each of the documents(probably, you should pass the document _id as a key prop in the row components)
<div className="row">
{notes.map((item) => {
return (
<div key={note._id} className="col-md-6">
<Component item={item} />
</div>
);
})}
</div>
I am using React and I have an array of data objects ("items"). I am trying to display this list of objects such that each object is its own component. So I'm calling "items.map" to map each item to a component and render it, like this:
return (
<Fragment>
<h1>Items</h1>
<Card.Group itemsPerRow={8} >
{items.length > 0 ? ( items.map( (_item) => (
<Fragment key={_item.key}>
<MyItem example={4} item={_item} />
</Fragment>
))
) : (<p>No items!</p>)}
</Card.Group>
</Fragment>
)
Here is the code for MyItem:
const MyItem = (example, item) => {
console.log(example);
console.log(item);
return (<Fragment>
<div style={{margin: "1em"}}>
<Card>
<Image src={item.image} wrapped ui={false} />
<Card.Content>
<Card.Header>{item.name}</Card.Header>
<Card.Description>
<p>Date Received: {item.dateReceived.toLocaleDateString()}</p>
</Card.Description>
</Card.Content>
</Card>
</div>
</Fragment>);
}
However, I'm getting an error saying that "item" is null in MyItem.js, while the list of items is definitely not null. Similarly, when I pass in the number 4 to the "example" prop, and I do "console.log(example)" it prints out the empty object "{}".
I should note that my page previously did display everything when both pieces of code were combined on the same page (i.e. there was no "MyItem" component). The reason I decided to make it a component was because I'm iterating over this map on multiple pages and it would be redundant code. This way, I can just call <MyItem item{_item} /> and it will display the same thing on every page that shows these items.
However, now that I have refactored my code to place the mapping inside of the component, it is no longer working. What am I doing wrong here? Is this even possible, or should I just go back to what I had before?
As mentioned in the above comment:
const MyItem = ({example, item})
This solves the problem.
I am trying to get 10 usernames back when I type a keystroke.
For now it only gives me a Username back if the username is exactly in the jsonplaceholder list. So when i type "Karia" nothing comes back until I type "Karianne"
So for example if the Input gets the first letter "A", I want to give back the first 10 Items which are matching from the jsonplaceholder list. If I put in an "R", after that, so its "Ar" I want to get back the first 10 matching "Ar" usernames, like Aron, Ariel, Aria, etc.
Does someone have an Idea?
export const Search = () => {
const [user, setUser] = useState(null);
const [searchQuery, setSearchQuery] = useState("")
useEffect(() => {
if (searchQuery.length > 0) {
const fetchFunc = async () => {
const response = await fetch(`https://jsonplaceholder.typicode.com/users?username=${searchQuery}`)
const resJSON = await response.json();
setUser(resJSON[0]);
};
fetchFunc();
}
}, [searchQuery]);
return (
<Flex className={styles.search__container}>
<Flex className={styles.search__elements}>
<InputGroup className={styles.search__input}>
<InputRightElement
className={styles.search__inputElements}
children={<RiSearchLine className={styles.search__icon} />} />
<Input
className={styles.search__users}
type='search'
placeholder='Search'
onChange={event => setSearchQuery(event.target.value)}
/>
{user ? (
<div>
<h3>{user['name']}</h3>
<h3>{user['username']}</h3>
<h3>{user['email']}</h3>
</div>
) : (
<p>No user found</p>
)}
</InputGroup>
</Flex>
</Flex>
)
}
The main limitation here is on the API side. Your API should supply you with the similar names. If it doesn't, then you can't do much.
Maybe the API provides a way to retrieve users with partial names (but I doubt it would be the case).
Otherwise, you can retrieve all users once,and simply display the one that fits your requirements, every time you write something.
To sum up:
When your component is mounted (at the beginning), fetch all users, and store them. You will perform this API call only once.
Then, every time you write something, just take the 10 users that have a name that include what you wrote.
Ideally, this should be handled by the API, and you should be concerned about when to trigger or re-trigger the API call.
API gets you a list of names, you slice a set of 10 from the list of names and set it in users, and then simply map them in your UI.
Also, you could maybe further optimise the function debouncing the API call.