React how to use a state from another component? - react-hooks

I am new to programming and try to learn to react and hands-on some real projects. I am trying to sort out a FreeCodeCamp drum-machine program and I am stuck at trying to use a state from one component to another one. Thank you for any help from you guys.
Please see the source component below:
import React,{useState} from 'react';
import './DrumControl.scss';
import { Switch } from 'antd';
import 'antd/dist/antd.css';
const DrumControl = () => {
const [isOn,setIsOn] = useState(false);
const [bankName,setBankName] = useState("Heater 1");
const [info,setInfo] = useState("");
const onOff = () =>{
isOn ? setIsOn(false) : setIsOn(true);
setInfo("");
}
const changeBankName = ()=>{
bankName === "Heater 1" ? setBankName("Piano") : setBankName("Heater 1");
setInfo(bankName);
}
console.log(info);
return (
<div className="drum-control">
<header>
<a className="navbar-brand text-dark" href="#">
ABC
</a>
</header>
<p className="text-dark fw-bold">Power</p>
<Switch onClick={onOff}/>
<p id="display">{info}</p>
<input type="range" className="form-range" min="0" max="100" id="volume-control"/>
<p className="text-dark fw-bold">Bank</p>
<Switch onClick={changeBankName}/>
</div>
);
}
export default DrumControl;
I am trying to use the bankName from the codes above in following component
import React,{useState} from 'react';
import {bankOne,bankTwo} from './Bank.js';
import {bankName} from './DrumControl';
const Drumpad = () =>{
const [bank,setBank] = useState(bankOne);
const changeBank = () =>{
bankName === "Heater 1" ? setBank(bankOne) : setBank(bankTwo);
}
return(
<h1 className="drum-pad">{bankOne[0].id}</h1>
);
}
export default Drumpad;
Anyway or alternative to sort this out ?

Ok all sorted now, import pubhub.js
https://www.npmjs.com/package/pubsub-js
publisher from drumcontrol
const pubsub = () =>{
PubSub.publish('changeBank',{bankName})
}
subscribe in Drumpad
useEffect(
()=>{
const mySub = PubSub.subscribe('changeBank',chooseBank);
return () => {
PubSub.unsubscribe(mySub);
};
},[]
);
const chooseBank = (changeBank,{bankName}) => {
bankName === 'Heater 1' ? setBank(bankOne) : setBank(bankTwo);
}

Related

Getting Invariant Violation : invariant violation 47 on mutation query in appolo graphql

I am using a mutation query to take the input from user and update it in database but while updating it is throwing this error invariant violation which I am not able to understand, In mutation I have four objects with min and max value that is coming from user:
export const ADD_INSIGHT_META_DATA = gql`
mutation MyMutation ($data : [projectInsightsMetadata_insert_input!]!) {
insert_projectInsightsMetadata(objects: $data) {
returning {
id
createdAt
}
}
}
`
This is how I am using the above query :
export const updateScheduleInsightMetaData = async(InsertData:any )=>{
const response:ApolloQueryResult<any> = await client.query({
query:ADD_INSIGHT_META_DATA,
context:{
role:"updateMasterPlan",
token:getProjectExchangeToken()
},
fetchPolicy: 'network-only',
variables:{
data:InsertData
}
})
return response.data;
}
Now I am using updateScheduleInsightMetaData function in one of code :
import React, { useContext, useEffect, useState } from "react";
import { IconButton, makeStyles, Paper, TextField, Typography } from "#material-ui/core";
import { useParams } from "react-router-dom";
import { Button } from "#material-ui/core";
import { Box } from "#mui/system";
import {getScheduleInsightMetaData,updateScheduleInsightMetaData} from "./InsightsSettingsActions";
import { setIsLoading } from "src/modules/root/context/authentication/action";
import { stateContext } from "src/modules/root/context/authentication/authContext";
import Notification, { AlertTypes } from "src/modules/shared/components/Toaster/Toaster";
import { projectDetailsContext } from "src/modules/baseService/projects/Context/ProjectDetailsContext";
import {
decodeExchangeToken,
getProjectExchangeToken
} from "../../../../../services/authservice";
import "./InsightsSettings.scss";
import NoDataMessage from "src/modules/shared/components/NoDataMessage/NoDataMessage";
interface Params {
projectId:any
}
interface InputType{
min:number,
max:number
}
export const noPermissionMessage = "You don't have permission to view project insight settings";
const InsightsSettings: React.FC =()=>{
const { projectDetailsState }: any = useContext(projectDetailsContext);
const { dispatch, stateCont }: any = useContext(stateContext);
const {projectId} = useParams<Params>();
const [hasCreateAccess, setCreateAccess] = useState<boolean>(false);
const [informationalConstraints, setInformationalConstraints] = useState<any>({min:Number(""),max:Number("")});
const [rfiResponse, setRfiResponse] = useState<any>({min:Number(""),max:Number("")});
const [physicalConstraints, setPhysicalConstraints] = useState<any>({min:Number(""),max:Number("")});
const [managementConstraints, setManagementConstraints] = useState<any>({min:Number(""),max:Number("")});
const tenantId = decodeExchangeToken().tenantId;
console.log("informationalConstraints",informationalConstraints);
console.log("rfiResponse",rfiResponse);
console.log("physicalConstraints",physicalConstraints);
console.log("managementConstraints",managementConstraints);
const projectToken = getProjectExchangeToken();
useEffect(()=>{
setCreateAccess(decodeExchangeToken(projectToken).allowedRoles.includes("viewMasterPlan"))
},[projectToken])
const navigateback = () => {
// props.navBack();
}
useEffect(()=>{
const token = projectDetailsState.projectToken;
fetchInsightsData(projectId,tenantId,token)
},[projectId,tenantId])
const fetchInsightsData = async(projectId:any,tenantId:any,token:any)=>{
try{
// const tenantId = decodeExchangeToken().tenantId;
// const token = projectDetailsState.projectToken;
dispatch(setIsLoading(true));
const res = await getScheduleInsightMetaData(projectId, tenantId ,token)
dispatch(setIsLoading(false));
}catch(err){
console.log("error in fetching insights metadata",err)
Notification.sendNotification('An error occured while fetching insights metadata', AlertTypes.warn);
dispatch(setIsLoading(false));
}
}
const handleInformationalInputChange = (e:any)=>{
setInformationalConstraints((prevState:any)=>({...prevState,[e.target.name]:Number(e.target.value)}))
}
const handleRfiInputChange = (e:any)=>{
setRfiResponse((prevState:any)=>({...prevState,[e.target.name]:Number(e.target.value)}))
}
const handlePhysicalInputChange = (e:any)=>{
setPhysicalConstraints((prevState:any)=>({...prevState,[e.target.name]:Number(e.target.value)}))
}
const handleManagementInputChange = (e:any)=>{
setManagementConstraints((prevState:any)=>({...prevState,[e.target.name]:Number(e.target.value)}))
}
const handleUpdate = async(e:any,informationalConstraints:any,rfiResponse:any,physicalConstraints:any,managementConstraints:any)=>{
try{
dispatch(setIsLoading(true));
const data = {
LeadtimeMgmntConstraints:managementConstraints,
LeadtimePhysicalConstraints:physicalConstraints,
ChangeOrderIssueReview:rfiResponse,
RFIReviewResponse:informationalConstraints
}
const response = await updateScheduleInsightMetaData(data)
// const response = await updateScheduleInsightMetaData(managementConstraints,physicalConstraints,rfiResponse,informationalConstraints)
Notification.sendNotification("Successfully updated insights", AlertTypes.success);
dispatch(setIsLoading(false));
}catch(err){
dispatch(setIsLoading(false));
Notification.sendNotification(err, AlertTypes.warn);
console.log(err)
}
}
return(
<>
{hasCreateAccess?
<div className="InsightsSettings">
<>
<div className="InsightsSettings__header">
<Typography component="p">Insight Settings</Typography>
</div>
<div className="InsightsSettings__input_area">
<div className="InsightsSettings__individual_box">
<Typography component="p">How far ahead of an activity start does the team review and resolve management or informational constraints?</Typography>
<div className="InsightsSettings__constraints">
<input name="min" className="InsightsSettings__constraints__style" value={informationalConstraints.min} placeholder="min" onChange={handleInformationalInputChange}/>
<input name="max" className="InsightsSettings__constraints__style" value={informationalConstraints.max} placeholder="max" onChange={handleInformationalInputChange}/>
</div>
</div>
<div className="InsightsSettings__individual_box">
<Typography component="p">What is the average (or typical) RFI design response period for this project?</Typography>
<div className="InsightsSettings__constraints">
<input name="min" className="InsightsSettings__constraints__style" value={rfiResponse.min} placeholder="min" onChange={handleRfiInputChange}/>
<input name="max" className="InsightsSettings__constraints__style" value={rfiResponse.max} placeholder="max" onChange={handleRfiInputChange}/>
</div>
</div>
<div className="InsightsSettings__individual_box">
<Typography component="p">How far ahead of an activity start does the team review and resolve physical or site constraints ?</Typography>
<div className="InsightsSettings__constraints">
<input name="min" className="InsightsSettings__constraints__style" value={physicalConstraints.min} placeholder="min" onChange={handlePhysicalInputChange}/>
<input name="max" className="InsightsSettings__constraints__style" value={physicalConstraints.max} placeholder="max" onChange={handlePhysicalInputChange}/>
</div>
</div>
<div className="InsightsSettings__individual_box">
<Typography component="p">How far ahead of an activity start does the team review and resolve management or informational constraints?</Typography>
<div className="InsightsSettings__constraints">
<input name="min" className="InsightsSettings__constraints__style" value={managementConstraints.min} placeholder="min" onChange={handleManagementInputChange}/>
<input name="max" className="InsightsSettings__constraints__style" value={managementConstraints.max} placeholder="max" onChange={handleManagementInputChange}/>
</div>
</div>
</div>
</>
<div className="InsightsSettings__action-button">
<Button data-testid={'cancel-update'} variant="outlined" onClick={navigateback} className="cancel-button">
Cancel
</Button>
<Button
variant="outlined"
className="update-button"
onClick={(e:any)=>{handleUpdate(e,informationalConstraints,rfiResponse,physicalConstraints,managementConstraints)}}
>
Update
</Button>
</div>
</div>: (
<div className="noCreatePermission-insight">
<div className="no-permission-insight">
<NoDataMessage message={noPermissionMessage}/>
</div>
</div>
) }
</>
)
}
export default InsightsSettings
When I am clicking on update button to make the insertion in database I am getting invariant violation: 47 error ,I am pasting the error here
Invariant Violation: Invariant Violation: 47 (see https://github.com/apollographql/invariant-packages)
at new InvariantError (http://localhost:3000/static/js/vendors~main.chunk.js:327507:24)
at invariant (http://localhost:3000/static/js/vendors~main.chunk.js:327521:11)
at getQueryDefinition (http://localhost:3000/static/js/vendors~main.chunk.js:9716:230)
at StoreReader.diffQueryAgainstStore (http://localhost:3000/static/js/vendors~main.chunk.js:2449:286)
at InMemoryCache.diff (http://localhost:3000/static/js/vendors~main.chunk.js:1132:29)
at http://localhost:3000/static/js/vendors~main.chunk.js:4864:28
at perform (http://localhost:3000/static/js/vendors~main.chunk.js:1264:31)
at InMemoryCache.batch (http://localhost:3000/static/js/vendors~main.chunk.js:1288:7)
at InMemoryCache.performTransaction (http://localhost:3000/static/js/vendors~main.chunk.js:1321:17)
at QueryInfo.markResult (http://localhost:3000/static/js/vendors~main.chunk.js:4842:20)
at http://localhost:3000/static/js/vendors~main.chunk.js:5713:19
at both (http://localhost:3000/static/js/vendors~main.chunk.js:10788:20)
at http://localhost:3000/static/js/vendors~main.chunk.js:10777:26
at new Promise (<anonymous>)
at Object.then (http://localhost:3000/static/js/vendors~main.chunk.js:10776:16)
at Object.next (http://localhost:3000/static/js/vendors~main.chunk.js:10791:39)
at notifySubscription (http://localhost:3000/static/js/vendors~main.chunk.js:332559:18)
at onNotify (http://localhost:3000/static/js/vendors~main.chunk.js:332603:3)
at SubscriptionObserver.next (http://localhost:3000/static/js/vendors~main.chunk.js:332652:5)
at http://localhost:3000/static/js/vendors~main.chunk.js:10848:23
at Array.forEach (<anonymous>)
at iterateObserversSafely (http://localhost:3000/static/js/vendors~main.chunk.js:10847:23)
at Object.next (http://localhost:3000/static/js/vendors~main.chunk.js:10586:87)
at notifySubscription (http://localhost:3000/static/js/vendors~main.chunk.js:332559:18)
at onNotify (http://localhost:3000/static/js/vendors~main.chunk.js:332603:3)
at SubscriptionObserver.next (http://localhost:3000/static/js/vendors~main.chunk.js:332652:5)
at Object.next (http://localhost:3000/static/js/vendors~main.chunk.js:6773:22)
at notifySubscription (http://localhost:3000/static/js/vendors~main.chunk.js:332559:18)
at onNotify (http://localhost:3000/static/js/vendors~main.chunk.js:332603:3)
at SubscriptionObserver.next (http://localhost:3000/static/js/vendors~main.chunk.js:332652:5)
at notifySubscription (http://localhost:3000/static/js/vendors~main.chunk.js:332559:18)
at onNotify (http://localhost:3000/static/js/vendors~main.chunk.js:332603:3)
at SubscriptionObserver.next (http://localhost:3000/static/js/vendors~main.chunk.js:332652:5)
at http://localhost:3000/static/js/vendors~main.chunk.js:7061:18
After going to the github url provided in error i.e https://github.com/apollographql/invariant-packages it tells to go into particular file in your node-modules to get the more understanding of invariant number error
node_modules/#apollo/client/invariantErrorCodes.js
after going into above file they have provided some extra information related to error code so for me I was getting invariant violation: 47
47: {
file: "#apollo/client/utilities/graphql/getFromAST.js",
node: invariant(queryDef && queryDef.operation === 'query', 'Must contain a query definition.')
},
In my case I am having mutation query and trying to query it instead of doing mutation that's why I was getting error so the changes that I did in my code to make it working is :
Instead of doing this:
export const updateScheduleInsightMetaData = async(InsertData:any )=>{
const response:ApolloQueryResult<any> = await client.query({
query:ADD_INSIGHT_META_DATA,
context:{
role:"updateMasterPlan",
token:getProjectExchangeToken()
},
fetchPolicy: 'network-only',
variables:{
data:InsertData
}
})
return response.data;
}
I needed to do this:
export const updateScheduleInsightMetaData = async(InsightsData:any )=>{
const response = await client.mutate({
mutation:ADD_INSIGHT_META_DATA,
context:{
role:"updateMasterPlan",
token:getProjectExchangeToken()
},
fetchPolicy: 'network-only',
variables:{
data:InsightsData
}
})
return response.data;
}

Why my reducer doesn't work when I click a button?

So I've just started learning redux, and I created a simple reducer which adds a number when you click on the button.
It looks like this:
const defaultState = {
cash: 5,
}
export const cashReducer = (state = defaultState, action) =>{
switch(action.type){
case 'ADD_CASHER':
return{...state, cash: state.cash + action.payload}
case 'GET_CASHER':
return{...state, cash: state.cash - action.payload}
default:
return state
}
}
index.js file:
import { createStore, combineReducers } from 'redux';
import { composeWithDevTools } from 'redux-devtools-extension';
import { cashReducer } from './cashReducer';
import { customReducer} from './customReducer';
const rootReducer = combineReducers({
cash: cashReducer,
custom: customReducer,
})
export const store = createStore(rootReducer, composeWithDevTools());
App.js file:
const App = () => {
const dispatch = useDispatch();
const cash = useSelector(state => state.cash.cash);
const addCash = (cash) =>{
dispatch({type: 'ADD_CASH', payload: cash});
}
const getCash = (cash) =>{
dispatch({type: 'GET_CASH', payload: cash});
}
return(
<div className="main">
<h1 style={{textAlign:'center'}}>{cash}</h1>
<button className="btn" onClick={() => addCash(Number(prompt()))}>add cash</button>
<button className="btn" onClick={() => getCash(Number(prompt()))}>get cash</button>
</div>
)
}
And buttons look like this:
So when I click on the button it should receive a number through the prompt and add it to the current number. But when I click both of the buttons nothing happens.
Everything is pretty simple, so I can't figure out what could be the problem here.

Apollo Cache not updating when changing Query variables

I'm following this tutorial https://www.howtographql.com/react-apollo/0-introduction/ and I discovered an issue.
I have a component named LinkLists which displays a list of links and it's paginated.
import React, { useEffect } from "react";
import Link from "./Link";
import { useQuery } from "#apollo/client";
import { useNavigate } from "react-router-dom";
import { LINKS_PER_PAGE } from "../utilities/constants";
import FEED_QUERY from "../graphql/queries/feedLinks";
import NEW_LINKS_SUBSCRIPTION from "../graphql/subscriptions/newLinks";
import NEW_VOTES_SUBSCRIPTION from "../graphql/subscriptions/newVotes";
import getQueryVariables from "../utilities/getQueryVariables";
import getLinksToRender from "../utilities/getLinksToRender";
const LinkList = () => {
const navigate = useNavigate();
const isNewPage = window.location.pathname.includes("new");
const pageIndexParams = window.location.pathname.split("/");
const page = parseInt(pageIndexParams[pageIndexParams.length - 1]);
const pageIndex = page ? (page - 1) * LINKS_PER_PAGE : 0;
const { data, loading, error} = useQuery(FEED_QUERY, {
variables: getQueryVariables(isNewPage, page),
});
return (
<>
{loading && <p>Loading...</p>}
{error && <pre>{JSON.stringify(error, null, 2)}</pre>}
{data && (
<>
{getLinksToRender(isNewPage, data).map((link, index) => (
<Link key={link.id} link={link} index={index + pageIndex} />
))}
{isNewPage && (
<div className="flex ml4 mv3 gray">
<div
className="pointer mr2"
onClick={() => {
if (page > 1) {
navigate(`/new/${page - 1}`);
}
}}
>
Previous
</div>
<div
className="pointer"
onClick={() => {
if (page < data.feed.count / LINKS_PER_PAGE) {
const nextPage = page + 1;
navigate(`/new/${nextPage}`);
}
}}
>
Next
</div>
</div>
)}
</>
)}
</>
);
};
export default LinkList;
When next is clicked, it navigates to the next page and renders the next set of links correctly. But after the links are loaded and I try to go to a previous page with new variables, the data is not being updated. I get the recent data but on a different page which is supposed to render older data. I think it has to do something with the cache but I'm not really sure. I'm still learning about Apollo Client and I'm not sure what is going wrong especially that I followed a tutorial.

mapDispatchToProps not updating store

I'm working on a personal project with redux. My mapStateToProps function seems to me properly written. but when I try to use it to send an object to my store nothing works.
Here's my function:
const mapDispatchToProps = dispatch => {
return {
addOrder: (item) => {
dispatch(addOrder(item));
}
}
}
<div className="recordOrder">
<button onclick={() => this.props.addOrder(this.state)}>Enregistrer et lancer la commande</button>
</div>
And my reducer:
const initialState = {
orderList : []
}
console.log(initialState);
export default function rootReducer ( state= initialState, action){
const orderList = [...state.orderList];
let position
switch (action.type){
case ADD_ORDER:
return {
orderList : [...state.orderList, action.payload]
};
case DELETE_ORDER:
position = orderList.indexOf(action.payload)
orderList.splice(position, 1)
return {
orderList
}
default:
return state;
}
console.log(state)
}
My entire component as requested:
import React, { Component } from 'react';
import { NavItem } from 'react-bootstrap';
import menu from './menu';
import { connect } from 'react-redux';
import { addOrder} from '../action'
class getOrder extends Component {
state = {
number: `CMD-${Date.now()}`,
order:[],
total: 0 ,
menu:menu,
isPaid: false
}
addItem = (index) => {
const order = [...this.state.order];
const menu = [...this.state.menu];
let total = this.state.total;
const pizza = menu[index];
console.log(pizza);
let ind = order.findIndex((item) =>
item.article == pizza.name
)
if (ind === -1){
order.push({article: pizza.name, price: pizza.price, volume:1})
total = total + order[order.length-1].price
} else if (ind != -1){
order[ind].volume++
total = total + order[ind].price
}
this.setState({
order:order,
total:total
})
console.log("youpiii");
console.log(this.state.total);
console.log(this.state.order);
}
render() {
const menuDisplay= menu.map( (item) => {
return (
<div>
<img onClick={() => this.addItem(item.number)} src={`${process.env.PUBLIC_URL}${item.picture}`} alt="picture" />
<div className="tagPrice">
<p>{item.name}</p>
<p>{item.price} €</p>
</div>
</div>
)
});
const currentOrder = [...this.state.order]
const orderDisplay = currentOrder.map((item) => {
let price = item.price*item.volume;
console.log(price);
return (
<div>
<h1>{item.volume} × {item.article}</h1>
<p>{price} €</p>
</div>
)
} );
return (
<div className="takeOrder">
<div className="orderban">
<h1>Pizza Reflex</h1>
</div>
<div>
<div className="menuDisplay">
{menuDisplay}
</div>
<div className="orderBoard">
<h1>Détail de la commande N°{this.state.number}</h1>
{orderDisplay}
<div className="total">
<h2>Soit un total de {this.state.total} € </h2>
</div>
<div className="recordOrder">
<button onclick={() => this.props.addOrder(this.state)}>Enregistrer et lancer la commande</button>
</div>
</div>
</div>
</div>
);
}
}
const mapDispatchToProps = dispatch => {
return {
addOrder: (item) => {
dispatch(addOrder(item));
}
}
}
export default connect ( mapDispatchToProps) (getOrder);
Can someone tell me what I've missed ?
Thanks for your help !
What you are missing is more of your code it can not be solved with what you have.
In more details what I need is the this.state , combinedReducer
The easiest fix you can do now is changing yow mapDispatchToProps works better if it is an obj
const mapStateToProps = (state) => {
return {
// here you specified the properties you want to pass yow component fom the state
}
};
const mapDispatchToProps = {action1, action2};
export default connect ( mapDispatchToProps) (getOrder);
connectreceives two params mapStateToProps and mapDispatchToProps,
mapDispatchToProps is optional, but mapStateToProps is mandatory, there for you need to specified, if your are not going to pass anything you need to pass a null value
export default connect (null, mapDispatchToProps) (getOrder);
also avoid exporting components without a name
example
function MyButton () {}
const MyButtonConnect = connect(state, dispatch)(MyButton);
export default MyButtonConnect

Set state like this props in react

Hello i have this code
import React from 'react'
import Link from 'react-router/lib/Link'
import { connect } from "react-redux"
import { load } from '../../actions/customerActions'
import List from './list';
import MdAdd from 'react-icons/lib/md/add'
#connect(store => {
return {
customers: store.customer.customers
}
})
export default class Customer extends React.Component {
componentDidMount() {
this.props.dispatch(load({location:localStorage.getItem('locationb')}));
}
render() {
const { customers } = this.props;
const tea = customers.customers && customers.customers.map(customer => <List key={customer.profile} customer={customer} />) || [];
return(
<div class="container">
{ customers.customers ?
<div class="columns is-multiline mb-100">
{ tea }
</div>
: 'Não exitem Clientes'}
<Link to="/customer/create" class="button is-info btn-rounded" title="Novo"><MdAdd /></Link>
</div>
)
}
}
But i only have access to customers in render passing this props.
How can i pass customer to a state variable in component did mount or else ?
i mean customers const { customers } = this.props; how i make like this.setState({customers: customers}) Having in the beginning this.state(customers: [])
YOu can use
componentWillReceiveProps(newProps){
console.log(newProps.customers.customers)
this.setState({customers: newProps.customers.customers})
}
it works for me
thanks
Carlos Vieira

Resources