I try to use strapi for the first time with react and I can't understand how I can link upload (in strapi) image to my content, I know how upload, I know how post something but I don't know how link this. I readed a lot of times strapi documentation but I can't understand.
My code
function ProductCreateApi({ evtId }) {
const [image, setImage] = useState(null)
const [posts, setPosts] = useState([])
const [updatesData, setUpdatesData] = useState({
titleproductgroup: "",
})
function updateEdit(e) {
const newupdate = { ...updatesData }
newupdate[e.target.id] = e.target.value
setUpdatesData(newupdate)
console.log(newupdate)
}
const handleSubmit = async (e) => {
console.log('handleSubmit')
e.preventDefault()
const formData = new FormData()
formData.append('files', image) // the pic
formData.append('ref', 'api::product-group.product-group') // link with my table
formData.append('refId', evtId)
formData.append('field', 'picproductgroup') // the row
axios.post('http://localhost:1337/api/upload/', formData)
e.preventDefault()
const res = axios.post(`http://localhost:1337/api/product-groups/`, {
"data": {
titleproductgroup: updatesData.titleproductgroup
}
})
if (res.ok) {
console.log('res.ok')
console.log('res', res)
// imageUploaded()
}
}
const handleFileChange = (e) => {
console.log('handleFileChange')
console.log(e.target.files[0]) //this will give us an array and we want the first wone so we add 0
setImage(e.target.files[0])
}
return (
<div>
<h1> Upload Event Image</h1>
<form onSubmit={handleSubmit}>
<input onChange={(e) => updateEdit(e)} id="titleproductgroup" value={updatesData.titleproductgroup} type="text" placeholder={posts.titleproductgroup} />
<div>
<input type='file' onChange={handleFileChange} />
</div>
<input type='submit' value='Upload' className='btn' />
</form>
</div>
)
}
export default ProductCreateApi
In the comment I wrote what I understand from attributes
and here my "table"
Thanks for your help. I hope I can improve myself thanks to you
I find solution, I just change that
const handleSubmit = async (e) => {
console.log('handleSubmit')
e.preventDefault()
const formData = new FormData()
formData.append('files', image) // the pic
formData.append('ref', 'api::product-group.product-group') // link with my table
formData.append('refId', evtId)
//formData.append('field', 'picproductgroup') // the row
axios.post('http://localhost:1337/api/upload/', formData).then(res => {
console.log(res.data[0].id);
const res2 = axios.post(`http://localhost:1337/api/product-groups/`, {
"data": {
titleproductgroup: updatesData.titleproductgroup,
picproductgroup: res.data[0].id,
}
})
if (res2.ok) {
console.log('res.ok')
console.log('res', res2)
// imageUploaded()
}
}).catch(error => {
console.log(error.message);
});
//e.preventDefault()
}
const handleFileChange = (e) => {
console.log('handleFileChange')
console.log(e.target.files[0]) //this will give us an array and we want the first wone so we add 0
setImage(e.target.files[0])
}
return (
Related
today i have a problem with my searchbar.
const [posts, setPosts] = useState(null)
const [searchTerm, setSearchTerm] = useState("")
useEffect(() => {
const loadPosts = async () => {
try {
const post = await getAllPosts()
setPosts(post)
} catch (e) {
alert("Couldn't load posts")
}
}
loadPosts()
}, [])
return (
<div>
<input type={"text"} placeholder="Search..." onChange={event => {
setSearchTerm(event.target.value)
}}/>
</div>
)
}
This is my Searchbar Component. In the Index file, did i gave a props with.
const [posts, setPosts] = useState([])
const [searchTerm, setSearchTerm] = useState("")
useEffect(() => {
const loadPosts = async () => {
try {
const post = await getAllPosts()
setPosts(post)
} catch (e) {
alert("Couldn't load posts")
}
}
loadPosts()
}, [])
return (
<div className={styles.posts}>
<h1>Market-place Valando</h1>
<SearchList title={posts.filter(post => {
if (post.title.toLowerCase().includes(searchTerm.trim().toLowerCase()) && searchTerm.trim() !== "") {
return post.title
}
}).map(titles => {
{
{titles.title}
}
}
)}/>
{
posts.map(post => {
return (
<div key={post.id} className={styles.key}>
<h1>{post.title}</h1>
<Image width={1000} height={1000} src={post.image}/>
<p>Price: {post.price}.-</p>
<p>Description: {post.description}</p>
<Link href={`/posts/${post.id}`} passHref>
<a>Read more</a>
</Link>
</div>
)
})
}
</div>
)
}
I have a db.json file that i connected with an API File. In this Api File i made all the fetch stuff. This shouldnt be the problem. I think the problem is, that the filter doesnt work properly, with the titels.
You are correct, JavaScript filter does not return specific property values, but it returns the top entries of the array, a.k.a posts. So return post.title or return true will yield the same result. However, the problem in your code appears to be that you are not returning anything from the map function. All you need to do is to change it to the following:
.map(post => post.title)
Can someone please tell me why i am getting this error . I tried fixing it all day, but I could not fix it. So at last i had to come at stackoverflow
This is my code : App.js
import "./App.css";
function App() {
const [inputvalue, setInputvalue] = useState(" ");
const [apidata, setApidata] = useState([]);
const [finalpoint, setFinalpoint] = useState("");
useEffect(() => {
fetch(
`https://weatherapi-com.p.rapidapi.com/forecast.json?q=+${inputvalue}&days=3`,
{
method: "GET",
headers: {
"x-rapidapi-host": "weatherapi-com.p.rapidapi.com",
"x-rapidapi-key":
"7f89bf16ebmsh9dff0f23f963d34p190691jsn264543e18108",
},
}
)
.then((response) => {
return response.json();
})
.then((data) => {
setApidata(data);
})
.catch((err) => {
console.error(err);
});
}, [finalpoint]);
const onchangeinput = (e) => {
setInputvalue(e.target.value);
};
const onsubmithandler = (e) => {
e.preventDefault();
setFinalpoint(inputvalue);
};
return (
<div className="App">
<div className="main">
<h2>Welcome To weather App </h2>
</div>
<form onSubmit={onsubmithandler}>
<input type="text" value={inputvalue} onChange={onchangeinput} />
<button type="submit">Search</button>
</form>
{apidata.map((data, i) => {
return <h1>{data.current.feelslike_c}</h1>;
})}
</div>
//Map
);
}
export default App;
This is the error I am getting :
enter image description here
Check if you are receiving undefined here:
.then((data) => {
setApidata(data);
})
and overriding the state with undefined.
What I'm seeing is the api is initially returning an error object. Also, when the proper data is returned, it comes back as an object. When setting your state, you will have to set data inside of an array (if you want to use the map method). You will also have to handle the error by doing something like this:
import { useState, useEffect } from "react";
function App() {
const [inputvalue, setInputvalue] = useState(" ");
const [apidata, setApidata] = useState([]);
const [finalpoint, setFinalpoint] = useState("");
useEffect(() => {
fetch(
`https://weatherapi-com.p.rapidapi.com/forecast.json?q=+${inputvalue}&days=3`,
{
method: "GET",
headers: {
"x-rapidapi-host": "weatherapi-com.p.rapidapi.com",
"x-rapidapi-key": "7f89bf16ebmsh9dff0f23f963d34p190691jsn264543e18108"
}
}
)
.then((response) => {
return response.json();
})
.then((data) => {
console.log(data)
if (data.error) return null;
setApidata([data]);
})
.catch((err) => {
console.error(err);
});
}, [finalpoint]);
const onchangeinput = (e) => {
setInputvalue(e.target.value);
};
const onsubmithandler = (e) => {
e.preventDefault();
setFinalpoint(inputvalue);
};
console.log("test", apidata);
return (
<div className="App">
<div className="main">
<h2>Welcome To weather App </h2>
</div>
<form onSubmit={onsubmithandler}>
<input type="text" value={inputvalue} onChange={onchangeinput} />
<button type="submit">Search</button>
</form>
{apidata.length
? apidata.map((data, i) => {
return <h1 key={i}>{data.current.feelslike_c}</h1>;
})
: null}
</div>
//Map
);
}
see working example: https://codesandbox.io/s/eager-wind-06ywo?file=/src/App.js
I am trying to add Seach filter using the react, and using json data
I am trying to match it with the search term
Below is my code
const App = () => {
const [searchTerm, setSearchTerm] = useState([""])
const [query, setQuery] = useState("");
useEffect(() => {
const url = "https://60d075407de0b20017108b89.mockapi.io/api/v1/animals";
const fetchData = async () =>
{
try
{
const response = await fetch(url);
const json = await response.json();
console.log([json].query);
setQuery(json.query);
}
catch (error)
{
console.log("error", error);
}
};
fetchData();
}, []);
return (
<input type='text' placeholder='search....' onChange={event => { setSearchTerm(event.target.value) }} />
{
query.filter((val) => {
if (searchTerm === "s")
{
return val
}
else if (val.name.toLowerCase().includes(searchTerm.toLowerCase())) {
return val
}
else
return false
}).map((val) =>
{
return (
<div className='user' >
<p>{val.name}</p>
<p>age: {monthDiff(val.bornAt)} months</p>
</div>
);
})}
</div>
);
};
When I try to execute, I am getting this below error
can anyone explain why it is happening
> Uncaught TypeError: Cannot read properties of undefined (reading
> 'toLowerCase')
It looks like you're initializing query to a string instead of an array of strings.
Maybe try changing this:
const [query, setQuery] = useState("");
to
const [query, setQuery] = useState([""]);
Also, your searchTerm is initialized to an array: you might have just mixed those up :)
I am trying to implement load more button for my small project GiF generator. First I thought of appending next set of 20 response at the bottom, but failed to do.
Next, I thought of implementing loading the next set of 20 results by simply removing the current one. I tried to trigger a method on click of button, but I failed to do so. Its updating the state on second click of load more and then never updating it again.
Please help me find what I am missing, I have started learning React yesterday itself.
import React, { useEffect, useState } from 'react';
import './App.css';
import Gif from './Gif/Gif';
const App = () => {
const API_KEY = 'LIVDSRZULELA';
const [gifs, setGif] = useState([]);
const [search, setSearch] = useState('');
const [query, setQuery] = useState('random');
const [limit, setLimit] = useState(20);
const [pos, setPos] = useState(1);
useEffect(() => {
getGif();
}, [query])
const getGif = async () => {
const response = await fetch(`https://api.tenor.com/v1/search?q=${query}&key=${API_KEY}&limit=${limit}&pos=${pos}`);
const data = await response.json();
setGif(data.results);
console.log(data.results)
}
const updateSearch = e => {
setSearch(e.target.value);
}
const getSearch = e => {
e.preventDefault();
setQuery(search);
setSearch('');
}
const reload = () => {
setQuery('random')
}
const loadMore = () => { // this is where I want my Pos to update with 21 on first click 41 on second and so on
let temp = limit + 1 + pos;
setPos(temp);
setQuery(query);
}
return (
<div className="App">
<header className="header">
<h1 className="title" onClick={reload}>React GiF Finder</h1>
<form onSubmit={getSearch} className="search-from">
<input className="search-bar" type="text" value={search}
onChange={updateSearch} placeholder="type here..." />
<button className="search-button" type="submit">Search</button>
</form>
<p>showing results for <span>{query}</span></p>
</header>
<div className="gif">
{gifs.map(gif => (
<Gif
img={gif.media[0].tinygif.url}
key={gif.id}
/>
))}
</div>
<button className="load-button" onClick={loadMore}>Load more</button>
</div>
);
}
export default App;
Please, help me find, what I am doing wrong, As I know the moment I will update setQuery useEffect should be called with new input but its not happening.
Maybe try something like this:
// Fetch gifs initially and then any time
// the search changes.
useEffect(() => {
getGif().then(all => setGifs(all);
}, [query])
// If called without a position index, always load the
// initial list of items.
const getGif = async (position = 1) => {
const response = await fetch(`https://api.tenor.com/v1/search?q=${query}&key=${API_KEY}&limit=${limit}&pos=${position}`);
const data = await response.json();
return data.results;
}
// Append new gifs to existing list
const loadMore = () => {
let position = limit + 1 + pos;
setPos(position);
getGif(position).then(more => setGifs([...gifs, ...more]);
}
const getSearch = e => {
e.preventDefault();
setQuery(search);
setSearch('');
}
const updateSearch = e => setSearch(e.target.value);
const reload = () => setQuery('random');
Basically, have the getGifs method be a bit more generic and then if loadMore is called, get the next list of gifs from getGift and append to existing list of gifs.
I am unable to save description as part of the component's state. I can only save the title. How do I save title and description to the database?
const BlogCreate = ({ history }) => {
const [blogCreate, setBlogCreate] = useState({
title: "",
description: ""
});
const [editorState, setEditorState] = useState(
EditorState.createEmpty(),
);
const handleChange = ({ currentTarget }) => {
const { name, value } = currentTarget;
setBlogCreate({...blogCreate, [name]: value});
};
const onEditorStateChange = editorState => {
setEditorState(editorState);
};
const handleSubmit = async event => {
event.preventDefault();
const data = draftToHtml(convertToRaw(editorState.getCurrentContent()));
try {
await blogAPI.create(blogCreate, data);
} catch (error) {
console.log(error)
}
}
console.log(data);
}
return(
<Field type="text" name="title" error={errors.title} value={blogCreate.title}
onChange={handleChange}
/>
<Editor name="description" editorState={editorState} onEditorStateChange={editorState => onEditorStateChange(editorState)}
/>
<button type="submit">Save</button>
);
}
export default BlogCreate;
Based on the full code you've provided me, I realised that you aren't properly updating the blogCreate state whenever there is a change at the Editor component.
The onEditorStateChange() should be updating the blogCreate state, and in addition, changeValue() needs to return the result value.
const changeValue = editorState => {
const value = ....
return value;
};
const onEditorStateChange = editorState => {
const description = changeValue(editorState);
setBlogCreate({
...blogCreate,
description,
});
setEditorState(editorState);
};
This way, description will be properly updated on your state, and it will be sent to your server side when you make the blogAPI.create() request.