This is a chat application and crated with React.js and StreamChat API. Need to function according to the team or message types. Now it only functions as a message, team chat also message cannot create channels, etc. code for the team also functions well. the problem is the code does not select the right component according to the section. Need your help to select the correct component.
import React, {useState} from 'react'
import { useChatContext } from 'stream-chat-react';
import { initialState } from 'stream-chat-react/dist/components/Channel/channelState';
import {UserList, TeamChannelList} from './';
import { CloseCreateChannel } from './assets';
const ChannelNameInput =({channelName ='', setChannelName}) => {
const handleChange =(event) =>{
event.preventDefault();
setChannelName(event.target.value);
}
return(
<div className='channel-name-input__wrapper'>
<p>Name</p>
<input value={channelName} onChange={handleChange} placeholder="channel-name" />
<p>Add Members</p>
</div>
)
}
const CreateChannel = ({createType, setIsCreating}) => {
const {client, setActiveChannel } = useChatContext();
const [selectedUsers, setSelectedUsers] = useState([client.userID || '']);
const [channelName, setChannelName] = useState('');
return (
<div className='create-channel__container'>
<div className='create-channel__header'>
<p>{createType === 'team' ? 'Create a New Channel' : 'Send a Direct Message'}</p>
<CloseCreateChannel setIsCreating={setIsCreating}/>
</div>
{createType === 'team' && <ChannelNameInput channelName={channelName} setChannelName={setChannelName}/>}
<UserList setSelectedUsers={setSelectedUsers}/>
<div className='create-channel__button-wrapper'>
<p>{createType==="team"? "ceate channel": "create group"}</p>
</div>
</div>
)
}
export default CreateChannel
Related
I'm doing a broker simulator and I need to pass the data (side,price,volume,timestamp) into different tab, which is like grandparent's brother. The problem is I have no idea, how to transport data that far
Modalbuy.js
import React from "react";
import "./modal.css";
const Modalbuy = ({active, setActive,price}) => {
return (
<div className={active ? "modal active" : "modal"} onClick={() => setActive(false)}>
<div className="modal__content" onClick={e => e.stopPropagation()}>
<header>Make order</header>
<p>BUY {price}</p>
<input placeholder="Volume">{volume}</input>
<div>
<button onClick={() =>{this.props.addData("BUY", price, volume,)}}>Ok</button>
<button>Cancel</button>
</div>
</div>
</div>
)
}
export default Modalbuy;
Select.js
import React, {useState} from "react";
import './select.css'
import Modalbuy from "../popup/Modalbuy"
import Modalsell from "../popup/Modalsell"
import { useEffect } from "react";
const Select = () => {
const [value, setValue] = useState("");
const [usdrub, setUsdrub] = useState(Math.random() * (64-61) + 61);
useEffect(() => {
const interval = setInterval(() => {
setUsdrub(Math.random() * (64-61) + 61);
}, 10000);
return () => clearInterval(interval);
}, [])
const [rubusd, setRubusd] = useState(Math.random() * 2);
useEffect(() => {
const interval = setInterval(() => {
setRubusd(Math.random() * 2);
}, 10000);
return () => clearInterval(interval);
}, [])
function changeSelect(event) {
setValue(event.target.value)
}
const [modalBuyActive, setModalBuyActive] = useState(false)
const [modalSellActive, setModalSellActive] = useState(false)
function addData(side, price, volume, timestamp) {
this.setState({side:side, price:price, volume:volume, timestamp:timestamp})
}
return (
<div>
<select value = {value} onChange={changeSelect}>
<option>Choose instrument</option>
<option name="USD/RUB" value={usdrub}>USD/RUB</option>
<option name="RUB/USD" value={rubusd}>RUB/USD</option>
</select>
<div className="Curr">
<div className="Buy" name="buy"> <button className="Buy" type="btn" onClick={() => setModalBuyActive(true)}>BUY {value + 1} </button>
</div>
<div className="Sell" name="sell"><button className="Sell" type="btn" onClick={() => setModalSellActive(true)}>SELL {value}</button></div>
</div>
<Modalbuy active={modalBuyActive} setActive={setModalBuyActive} price={value + 1} addData={addData}/>
<Modalsell active={modalSellActive} setActive={setModalSellActive} price={value}/>
</div>
)
}
export default Select
Trading.js
import React from "react";
import Timer from "./Timer";
import Select from "./select_curr/Select";
const Trading = () => {
return (
<div>
<Timer/>
<Select/>
</div>
)
}
export default Trading;
Page.js
import React from 'react'
import { Tabs, TabList, TabPanel, Tab } from 'react-re-super-tabs'
import CustomTab from './customTab'
import Trading from '../trading/Trading.js'
import Table from '../archive/table'
const Page = () => {
return (
<div>
<Tabs activeTab='about'>
<TabList>
<Tab component={CustomTab} label='Trading' id='trading' />
<Tab component={CustomTab} label='Archive' id='archive' />
</TabList>
<TabList>
<TabPanel component={Trading} id='trading' />
<TabPanel component={Table} id='table' />
</TabList>
</Tabs>
</div>
)
}
export default Page;
So I need to make a table in Table.js and import there data I got from module dialogue
To summarize the way I understand your problem, The component Modalbuy need to share data with your component Table.
Here are some way I can advise you.
1. The common Parent manage the state
const Page = () => {
const [yourData, setYourData] = useState([])
return (
[...]
<TabPanel component={props=>(<Trading {...props} value={yourData} onChange={setYourData} />)} id='trading' />
<TabPanel component={props=>(<Table {...props} value={yourData} onChange={setYourData} />)} id='table' />
[...]
)
}
This implies intermediate component are in charge to follow those new props to Modalbuy
2. Using Redux librairy
Redux is basicly a librairy to help you to define a global state for your app. You define actions your components can call to transform this global state. On the other way, components can subscribe to that state to be refreshed when a change happen.
Don't hesitate to have a look to tutorials https://react-redux.js.org/tutorials/quick-start
3. Using React Context
export const YourDataContext = React.createContext({})
const Page = () => {
const [yourData, setYourData] = useState([])
return (
<YourDataContext.Provider value={{yourData, setYourData}}>
[...]
</YourDataContext.Provider>
)
}
const Modalbuy = ({active, setActive,price}) => {
const { yourData, setYourData } = React.useContext(YourDataContext)
[...]
})
You define a context YourDataContext. You share a value to this context, here we create a state and passing the getter/setter. All child of the Provider can access the attribute value with the hook React.useContext(YourDataContext)
I am new to React and using React 18 in this app. My problem is that if I click one button inside a map function, it reflects information about all the items. I want only that item information to show for which I clicked the button. The isShown === true part in the CountryInfo.js file is what should reflect only one item; currently clicking the show button shows all item information on the UI (I don't want this to happen). How do I do this?
Visually, this is my UI,
If you see the image above, clicking any show button returns all countries information, which should not happen.
Below is my code:
App.js
import { useState, useEffect } from 'react';
import axios from "axios";
import CountryInfo from './components/CountryInfo';
const App = () => {
const [countries, setCountries] = useState([]);
const [searchCountry, setSearchCountry] = useState("");
const handleCountryChange = event => {
setSearchCountry(event.target.value);
}
const getAllCountriesData = () => {
axios.get("https://restcountries.com/v3.1/all")
.then(response => {
setCountries(response.data);
})
}
useEffect(() => {
getAllCountriesData();
}, []);
return (
<>
<h2>Data for countries</h2>
find countries:
<input value={searchCountry} onChange={handleCountryChange} />
{searchCountry.length > 0 && <CountryInfo countries={countries} searchCountry={searchCountry} />}
</>
)
}
export default App;
CountryInfo.js
import React from "react";
import { useState } from "react";
const CountryInfo = ({ countries, searchCountry }) => {
const [isShown, setIsShown] = useState(false);
let filteredList = countries.filter(country =>
country.name.common.toLowerCase().includes(searchCountry.toLowerCase()));
const handleClick = () => {
setIsShown(true);
}
if (filteredList.length > 10) {
return <div>Too many matches, specify another filter</div>
}
else {
return filteredList.map(country => {
return (
<>
<div key={country.name.common}>
{!isShown &&
<div>
{country.name.common}
<button type="submit" onClick={handleClick}>show</button>
</div>
}
{isShown &&
<div key={country.name.common}>
<h2>{country.name.common}</h2>
<p>
Capital: {country.capital}
{'\n'}
Area: {country.area}
</p>
Languages:
<ul>
{
Object.values(country.languages)
.map((language, index) => <li key={index}>{language}</li>)
}
</ul>
<img src={country.flags.png} alt={`${country.name.common} flag`} height={150} />
</div>
}
</div>
</>
)
})
}
}
export default CountryInfo;
I'm trying to update my category. I want to update only categoryname, categoryDescription and categoryImage inside the category data. For this, I pull the data from the API with the id I wrote in c# on the backend to show the first state of the data to the user, there is no problem there, but when I try to make changes to a data, nothing appears on the screen in the browser and the following errors appear in the console. Actually ı am new in react. How can I fix that problem?
ERRORS
Uncaught TypeError: Cannot read properties of undefined (reading 'categoryName')
The above error occurred in the <UpdateCategory> component:
My CategoryList.js
I send the id of the category I clicked to UpdateCategory.js from here and I do the editing there.
CategoryList.js shows only my categories
import { Button } from "bootstrap";
import React, { useContext } from "react"
import { Link, Router } from "react-router-dom";
import { CategoryContext } from "../Contexts/CategoryContext";
import "../Css/Categories.css"
export default function CategoryList() {
const { Categories } = useContext(CategoryContext)
const truncateOverview = (string, maxLength) => {
if (!string) return null;
if (string.length <= maxLength) return string;
return `${string.substring(0, maxLength)} ...`;
}
return (
<div className="categories">
{Categories.map((category, i) => (
<Link className="category" to={`/ProductList/${category.categoryId}`} key={i}>
<div className="inner-category">
<div className="image-body">
<img src={category.categoryImage} className="image" alt="" />
</div>
<div className="category-body">
<div>
<h5 className="">{category.categoryName}</h5>
<p className="">{truncateOverview(category.categoryDescription, 50)}</p>
<Link to={`/UpdateCategory/${category.categoryId}`}>
<button className ="btn btn-warning" variant="primary" >
EDIT
</button>
</Link>
</div>
</div>
</div>
</Link>
))}
</div>
)
}
My UpdateCategory.js
import React, { useState, useEffect } from 'react';
import { useParams } from 'react-router-dom';
import Button from 'react-bootstrap/Button';
import Col from 'react-bootstrap/Col';
import Form from 'react-bootstrap/Form';
import InputGroup from 'react-bootstrap/InputGroup';
import Row from 'react-bootstrap/Row';
import axios from 'axios';
export default function UpdateCategory() {
const { id } = useParams()
const url = `http://localhost:64082/api/categories/getbyid/${id}`
const [category, setCategory] = useState({})
const fetchData = () => {
axios.get(url)
.then(response => {
setCategory(response.data)
})
.catch(error => {
console.log(error)
})
}
useEffect(() => {
fetchData()
});
const handleInputChange =(e)=>{
setCategory(e.target.category)
}
const handleSubmit = (event) => {
event.preventDefault();
const data = new FormData(event.target);
fetch(`http://localhost:64082/api/categories/update`, {
method: 'POST',
body: data,
})
}
return (
<div>
<form >
<label htmlFor="inputName">Category Name</label>
<input type="text"
className="form-control"
name="categoryName"
value={category.categoryName}
onChange={handleInputChange}
/>
<label htmlFor="inputName">Category Description</label>
<input type="text"
className="form-control"
name="categoryDescription"
value={category.categoryDescription}
onChange={handleInputChange}
/>
<label htmlFor="inputName">Category Image</label>
<input type="text"
className="form-control"
name="categoryImage"
value={category.categoryImage}
onChange={handleInputChange}
/>
<div>
<button onSubmit={handleSubmit} className="btn btn-danger" >EDIT</button>
</div>
</form>
</div>
)
}
The error probably comes about because of the render in UpdateCategory. The code tells it to render three properties of the category object. But initially, category is an empty object. So it will fail there.
There's another point you need to modify though, in the useEffect(). What you have right now will not trigger on the initialisation of the component. Change it to:
useEffect(() => {
fetchData()
}, []);
Since you're not using typescript you'd also probably want some kind of guard on your render to be safe. So for example something like this:
return category.categoryName && category.categoryDescription && category.categoryImage && (
// your render code in here
);
But that's quite long-winded. You could write an if clause before the return () for the render, asking if those properties exist and returning a blank component instead, or some alternate text.
You could also perhaps provide a default version of the category when initialising the hook.
const [category, setCategory] = useState({
categoryName: 'Default',
categoryDescription: 'Default description',
categoryImage: null
});
This would be a simpler effort than the guard block, and you'd still need the useEffect update.
In UpdateCategory.js,edit;
const [category, setCategory] = useState([]) // not useState({})
The default value of this state should be an empty array. Thanks to empty array, It will not be able to return with map until data comes from api, because its length is 0.
I want to fetch the data when the button is clicked but the Newsitem component is running first and then updating the value of data_grabber. That means it is displaying the defalut values rather than the data that I fetched from the newsapi. After displaying the newsitem component with default values, data_grabber is updating the fetched data.
What can be the solution?
App.js
function App() {
const [input_data, setInput_data] = useState("");
const [btn_data, setBtn_data] = useState("");
const [data_grabber, setData_grabber] = useState([]);
return (
<>
<Navbar
input_data={input_data}
setInput_data={setInput_data}
setBtn_data={setBtn_data}
btn_data={btn_data}
data_grabber={data_grabber}
setData_grabber={setData_grabber}
/>
{data_grabber? data_grabber.map((news_data)=>{
return(
<NewsItem news_data={news_data}/>
)
}):<div>No data available</div>}
</>
);
}
export default App;
Navbar.js
import { useEffect } from "react";
export default function Navbar(props) {
const onClicker = async (e) => {
e.preventDefault();
props.setBtn_data(props.input_data);
};
useEffect(() => {
const fetcher = async () => {
const link = `https://newsapi.org/v2/everything?q=${props.btn_data}&apiKey=API_KEY`;
const raw_data = await fetch(link);
const data = await raw_data.json();
console.log(data);
props.setData_grabber(data.articles)
};
fetcher();
}, [props.btn_data]);
return (
<div>
<form className="d-flex">
<input
onChange={(e) => props.setInput_data(e.target.value)}
value={props.input_data}
className="form-control me-2"
type="search"
placeholder="Search"
aria-label="Search"
/>
<button
className="btn btn-outline-success"
type="submit"
onClick={onClicker}
>
Search
</button>
</form>
</div>
NewsItem.js
import React, { Component } from "react";
export default class NewsItem extends Component {
render() {
const {title, description, url, urlToImage} = this.props.data
const defaultImage = `https://blogger.googleusercontent.com/img/a/AVvXsEh20SgNNsDlKyWWmB7XgB5SfFY10M6CqJAq93HwGtssTn2cWz6w9zHPjXf91WwoWr27QeaC4HsGv2NxPOXUdvk6xodUojnw8rUuAkEMY3Qb4ucoVpN3nSyF8JW_xVDWa2aSMEWH387hPsfouSJyClLNburIcDbXIeJamuTHwiSvw4hdNnqeeICcvg1wrQ=w1200-h630-p-k-no-nu`
return (
<div>
<div className="card">
<img src={urlToImage?urlToImage:defaultImage} className="card-img-top" alt="..." />
<div className="card-body">
<h5 className="card-title">{title?title:'No title available'}</h5>
<p className="card-text">
{description?description.slice(0, 50):"no description available"}...
</p>
<a href={url} target="_blank" rel="noreferrer"className="btn btn-primary">
read more
</a>
</div>
</div>
</div>
);
}
}
One fix could be to
make a variable of the updated state:
in the UseEffect ,
add :
const updated = data.articles
props.setData_grabber(updated)
Check whether data_grabber array is empty or not and then do the rendering inside App component as follows.
{
data_grabber.length > 0 ? (
data_grabber.map((news_data) => {
return <NewsItem news_data={news_data} />;
})
) : (
<div>No data available</div>
);
}
{ data_grabber !== undefined && data_grabber.length > 0 ? data_grabber.map((news_data)=>{
return(
<NewsItem news_data={news_data}/>
)
}):<div>No data available</div>}
Check data_grabber is undefined or empty.
Then, fix NewsItem props.data like this.
export default class NewsItem extends Component {
render() {
const {title, description, url, urlToImage} = this.props.news_data
also fix here in useEffect
useEffect(() => {
const fetcher = async () => {
const link = `https://newsapi.org/v2/everything?q=${props.btn_data}&apiKey=c990aa0235da4635997afd1f7459860c`;
const raw_data = await fetch(link);
const data = await raw_data.json();
console.log(data);
if(data.articles){
props.setData_grabber(data.articles)
}
};
fetcher();
I'm trying to build a TicTacToe application.
Problem occured when I tried to convert from class to func. components.
I'm familiar with setting the state variable and the function to change the state of the variable, but passing into the return... i get confused.
import React from "react";
class Endgame extends React.Component {
state = {
tied: "You guys tied",
playerWin: "You win " + this.props.winner + " !!",
};
handleClick = () => {
this.props.endgame(false);
};
render() {
const { winner } = this.props;
const { tied, playerWin } = this.state;
return (
<div className="wrapper">
<div className="screen">
<p>{winner === "Tied" ? tied : playerWin}</p>
<button className="btn-primary" onClick={this.handleClick}>
Start again?
</button>
</div>
</div>
);
}
}
export default Endgame;
import React, { useState } from "react";
const Endgame=({winner,endgame})=>{
const [state,setState]=useState({
tied: "You guys tied",
playerWin: `You win ${winner} !!`,
})
const handleClick = () => {
endgame(false);
};
return (
<div className="wrapper">
<div className="screen">
<p>{winner === "Tied" ? state.tied : state.playerWin}</p>
<button className="btn-primary" onClick={handleClick}>
Start again?
</button>
</div>
</div>
);
}
export default Endgame;
here it is converted into functional component
You can easly transform this component in function component in this way:
import React, { useState } from "react";
const Endgame = ({ winner, endgame }) => {
const [tied, setTied] = useState("You guys tied");
const [playerWin, setPlayerWin] = useState("You win " + winner + " !!");
const handleClick = (e) => {
endgame(false);
};
return (
<div className="wrapper">
<div className="screen">
<p>{winner === "Tied" ? tied : playerWin}</p>
<button className="btn-primary" onClick={handleClick}>
Start again?
</button>
</div>
</div>
);
}
export default Endgame;
This is an intersting article that explains step by step how to convert component to funcional component.