I'm trying to pass the 'Username' component directly into the 'Comment' component, like I did with the 'ProfilePicture' component, but only the '#' symbol shows up and not the username. Please help, also thanks in advance!
//component
const ProfilePicture = (props) => {
return (
<div>
<img
className="ProfilePicture"
src={props.user.pfpUrl}
alt={props.user.name}
height={50}
width={50}
/>
</div>
)
};
// username component
const Username = (props) => {
return (
<div>
<p>#{props.user.username}</p>
</div>
)
};
// user's comment
const comment = {
username: "guest",
image: {
name: "Default Profile Image",
pfpUrl: 'https://static.vecteezy.com/system/resources/thumbnails/009/292/244/small/default-avatar-icon-of-social-media-user-vector.jpg'
}
}
const Comment = (props) => {
return (
<div>
<ProfilePicture user={props.image} />
<Username user={props.username} />
</div>
)
}
ReactDOM.render(
<Comment image={comment.image} username={comment.username} />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root">
<!-- This element's contents will be replaced with your component. -->
</div>
You need to access it like props.user in your Username component
//component
const ProfilePicture = (props) => {
return (
<div>
<img
className="ProfilePicture"
src={props.user.pfpUrl}
alt={props.user.name}
height={50}
width={50}
/>
</div>
)
};
// username component
const Username = (props) => {
return (
<div>
<p>#{props.user}</p> // YOU are passing user as a prop to username component
</div>
)
};
// user's comment
const comment = {
username: "guest",
image: {
name: "Default Profile Image",
pfpUrl: 'https://static.vecteezy.com/system/resources/thumbnails/009/292/244/small/default-avatar-icon-of-social-media-user-vector.jpg'
}
}
const Comment = (props) => {
return (
<div>
<ProfilePicture user={props.image} />
<Username user={props.username} />
</div>
)
}
ReactDOM.render(
<Comment image={comment.image} username={comment.username} />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
<div id="root">
<!-- This element's contents will be replaced with your component. -->
</div>
Change the <Username> in your Comment component to read:
<Username user={{username:props.username}} />
This matches the way you are retrieving the username later.
Related
How to create a button than once click the button will render just text by using react hook
const WelcomeButton = (props) => {
const[welcomeBtn, setwelcomeBtn] = useState()
const handelClick = () => {
if() {
retun <p>Hi John</p>
}
}
return (
<div>
<button onClick={handelClick}> Welcome </button>
</div>
)
;
};
I suggest using a state that tracks that the button has been clicked, and update/toggle this value in the handleClick callback. Conditionally render either the button or the welcome text based on this state.
const WelcomeButton = (props) => {
// initial state true to show button
const [welcomeBtn, setWelcomeBtn] = React.useState(true);
const handelClick = () => {
// toggle false to hide button and display welcome message
setWelcomeBtn(false);
};
return (
<div>
{welcomeBtn ? (
<button onClick={handelClick}> Welcome </button>
) : (
<p>Hi John</p>
)}
</div>
);
};
const rootElement = document.getElementById("root");
ReactDOM.render(
<WelcomeButton />,
rootElement
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.2/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.2/umd/react-dom.production.min.js"></script>
<div id="root" />
I'm new to Reactjs. I'm unable to extract image url from the API. I'm really sorry if similar type of threads already exist in stackoverflow. Full code is below.
The API I used is: https://api.thecatapi.com/v1/breeds
import React, { Component } from "react";
import ReactDOM from "react-dom";
const Cat = ({
cat: {name, image},
}) => {
return(
<div className='catMain'>
<div className='catImage'>
<img src={image.url} alt={name} />
</div>
</div>
)
}
class App extends Component {
state = {
data: [],
};
componentDidMount() {
this.fetchCatData();
}
fetchCatData = async () => {
const url1 = "https://api.thecatapi.com/v1/breeds"
const response = await fetch(url1)
const data = await response.json()
this.setState({
data,
})
}
render() {
return (
<div className='main'>
<div className="cats">
<div className="catsInfo">
{this.state.data.map((cat) => (
<Cat cat={cat}/>
))}
</div>
</div>
</div>
)
}
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);
If you want to display every cat even though they might not have an image, you can do this:
const Cat = ({ cat: { name, image } }) => {
return (
<div className="catMain">
{image && (
<div className="catImage">
<img src={image.url} alt={name} />
</div>
)}
</div>
);
};
Then you can just display whatever else you want about the cat, without having to worry about image issues.
You have an assumption that every cat has an image, that's not the case, therefore you can filter empty images beforehand (there are tons of solutions, conditional rendering can be done too):
// cat.image is an object, which is truthy value therefore you can filter by it.
this.state.data.filter(cat => cat.image).map(cat => <Cat cat={cat} />)
// OR, conditional rendering
this.state.data.map(cat => cat.image && <Cat cat={cat} />)
// Or in the component itself, etc.
const Cat = ({ cat: { name, image } }) => {
return image ? (
<div className="catMain">
<div className="catImage">
<img src={image.url} alt={name} />
</div>
</div>
) : (
<Placeholder />
);
};
Rendering Result components using map and passing props.
<div className="results">
{data.map((movie) => (
<Result
poster={movie.poster_path}
alt={movie.title}
key={movie.id}
id={movie.id}
/>
))}
</div>
My Result component that receives props
export default function Result(props) {
const { poster, alt, id } = props;
return (
<div className="result">
<Link to={`/results/${id}`}>
<img
src={
poster
? `https://image.tmdb.org/t/p/original/${poster}`
: "https://www.genius100visions.com/wp-content/uploads/2017/09/placeholder-vertical.jpg"
}
alt={alt}
/>
</Link>
</div>
);
}
I have my dynamic routes.
<Route path={"/results/:id"}>
<ResultPage />
</Route>
I have my dynamic ResultPage, but I don't know how to pass the Result component's props to this page.
export default function ResultPage(props) {
const { id } = useParams();
return (
<div className="resultPage">
<h3>this is page: {id}</h3>
{/* I WANT TO PASS & DISPLAY PROPS HERE */}
</div>
);
}
Result.jsx
export default function Result(props) {
const { poster, alt, id } = props;
const history = useHistory();
const handleClick = () => {
history.push({
pathname: `/results/${id}`,
state: {
poster,
alt
}
})
}
return (
<div className="result">
<img
onClick ={handleClick}
src={
poster
? `https://image.tmdb.org/t/p/original/${poster}`
: "https://www.genius100visions.com/wp-content/uploads/2017/09/placeholder-vertical.jpg"
}
alt={alt}
/>
</div>
);
}
ResultPage.jsx
export default function ResultPage(props) {
const { id } = useParams();
const location = useLocation();
return (
<div className="resultPage">
<h3>this is page: {id}</h3>
<p> {location.state.poster} </p>
</div>
);
}
Instead of Link component I have added an onClick event handler to the img tag and then in the handleClick method I'm useHistory.push() to send props from the Result Component to ResultPage component.
The location object has a state property, which now contains the props passed through the Result Component.
const App = () => {
const [searchTerm, setSearchTerm] = React.useState('');
const stories = [
...
];
const handleSearch = event => {
setSearchTerm(event.target.value);
};
const searchStories = stories.filter((story) => {
return story.title.includes(searchTerm);
})
return (
<div>
<h1>My Hacker Stories</h1>
<Search onSearch={handleSearch}/>
<hr />
<List list={searchStories}/>
</div>
);
};
const Search = (props) =>{
return (
<div>
<label htmlFor="search"><strong>Search:</strong></label> { ' '}
<input id='search' type='text' onChange={props.onSearch}/>
</div>
);
};
const List = ({list}) =>
list.map((item) =>
(
<div key={item.objectID}>
<span>
<a href={item.url}>{item.title}</a>
</span>
<span>{item.author}</span>
<span>{item.num_comments}</span>
<span>{item.points}</span>
</div>
)
)
I am trying to filter the List Component based on the search input. It's working unless if I put a search term in the input box. When I try to search an item, List is empty, nothing is showing, it's empty List, however, there is no error showing.
I've change your code a little to produce a runnable snippet which you can change back to your code,
just need to add another state for searchStories and use useEffect for filtering when searchTerm changes like this:
*Click the Run Code Snippet and type h so you can see how filter works
const App = () => {
const [searchTerm, setSearchTerm] = React.useState("");
const [searchStories, setSearchStories] = React.useState([]);
const stories = ["hello", "hi", "bye", "have a good day"];
const handleSearch = event => {
setSearchTerm(event.target.value);
};
React.useEffect(() => {
setSearchStories(
stories.filter(story => {
return story.includes(searchTerm);
})
);
}, [searchTerm]);
return (
<div>
<h1>My Hacker Stories</h1>
<Search onSearch={handleSearch} />
<hr />
<List list={searchStories} />
</div>
);
};
const Search = props => {
return (
<div>
<label htmlFor="search">
<strong>Search:</strong>
</label>{" "}
<input id="search" type="text" onChange={props.onSearch} />
</div>
);
};
const List = ({ list }) =>
list.map(item => (
<div key={item}>
{item}
{/* <span>
<a href={item.url}>{item.title}</a>
</span>
<span>{item.author}</span>
<span>{item.num_comments}</span>
<span>{item.points}</span> */}
</div>
));
const rootElement = document.getElementById("root");
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
rootElement
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
The filter function checks whether the searchTerm is present in our story item's title, but it's still too opinionated about the letter case. If we search for "react", there is no filtered "React" story in your rendered list. To fix this problem, we have to lower case the story's title and the searchTerm.
const App = () => {
...
const searchedStories = stories.filter(function(story) {
return story.title
.toLowerCase()
.includes(searchTerm.toLowerCase());
});
...
};
I have the following array:
const elements = [
{
title: "foo"
section: <div>Foo <button onClick={sayHello}>Greet</button></div>
},
{
title: "bar"
section: <div>Bar <button onClick={sayHello}>Greet</button></div>
}
];
I want to render the component with something like:
const someSections = this.state.elements.map((item, i) => (
<div key={i}>
{item.section}
</div>
));
...
render(){
return (
...
<div>
{someSections}
</div>
)
}
But I can't render them. The error is:
Uncaught Error: objects are not valid as a React child
Check the working solution:
const data = [
{
title: "foo",
section: <div>Foo <button>Greet</button></div>
},
{
title: "bar",
section: <div>Bar <button>Greet</button></div>
}
]
class App extends React.Component{
render(){
return(
<div>
{
data.map((item,i)=>{
return <div key={i}>{item.section}</div>
})
}
</div>
)
}
}
ReactDOM.render(
<App/>,
document.getElementById('app')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app'></div>
normally you would do something like this.
render(){
let someSections = this.state.elements.map((item, i) => (
<div key={i}>
{item.section}
</div>
));
return (
<div>
{someSections}
</div>
)
}