Compare Contract Settings Goerli on Etherscan - solidity

I recently took over a project from another developer who has been uncooperative in providing assistance. The project includes a contract deployed on the Rinkeby network and a decentralized exchange (DEX) developed for it. Users were able to test the DEX using our own platform, with liquidity added via the Uniswap interface. The contract includes the Uniswap V2Router contract to fetch liquidity and use it on our DEX. I have completed all necessary web3 setup, including changing the RPC port to 5 and adding the correct URL.
No error so far on my console.
SITE FOR REFERENCE: https://doxastaking.netlify.app/, It is deployed on GOERLI ETHER.
Recently, I migrated the project to the Goerli network. However, since the migration, I have not been able to purchase tokens using our DEX. Transactions go through, but the equivalent tokens are not assigned to my wallet. It is unclear to me whether the issue is with the contract or the web3 setup.
The web3 swap code:
import React, { Component } from "react";
import eth from "../../assets/eth.png";
import transfer from "../../assets/transfer.png";
import buyLoader from "../../assets/doxa-ico-loader.gif";
import { connect } from "react-redux";
import { connectWallet } from '../../redux/WalletAction';
import miniLogo from "../../assets/logo.png";
import "./scss/bs.css";
class Buydoxa extends Component {
constructor(props) {
super(props);
this.state = {
inputValue: '0',
doxaValue: 0
}
}
componentDidMount() {
const { web3Modal } = this.props.wallet
if (web3Modal.cachedProvider) {
this.props.connectWallet();
}
}
connectToWallet = async () => {
await this.props.connectWallet();
}
buyToken = async () => {
const queryParams = new URLSearchParams(window.location.search);
const id = queryParams.get('email');
let inputValue = parseFloat(this.state.inputValue);
if (inputValue >= 0.00001 && inputValue <= 10) {
const { web3, doxa, wallet, address } = this.props.wallet;
const value = this.state.inputValue.toString();
const buyValue = web3.utils.toWei(value, 'ether');
const tokenPrice = web3.utils.toWei('0.00001', 'ether');
const totalTokens = (web3.utils.toBN(buyValue).div(web3.utils.toBN(tokenPrice))).toString();
try {
this.setState({ loading: true })
const res = await wallet.methods.swapEthToDoxa(id).send({ from: address, value: buyValue });
this.setState({ loading: false })
} catch (err) {
this.setState({ loading: false })
if (err.message) {
alert(err.message)
} else {
alert("Something went wrong!")
}
}
} else {
alert("ETH should be between 0.00001 and 10");
return
}
}
updateInputValue = async (e) => {
let totalTokens;
if (e.target.value != '') {
totalTokens = parseFloat(e.target.value) / 0.00001;
}
this.setState({
inputValue: e.target.value,
doxaValue: totalTokens
});
}
render() {
return (
<div className="bs-container h-100">
<div className="bs-main">
<h2>swap your crypto</h2>
<div className="bs-input">
<div className="inpt-cont center mb-3">
<label>Enter ETH</label>
<input type="number" value={this.state.inputValue} onChange={e => this.updateInputValue(e)} />
</div>
<div className="img-cont">
<img src={eth} alt="eth" />
<p>ETH</p>
</div>
</div>
{/* image */}
<img src={transfer} className="transfer" alt="transfer" />
<div className="bs-input">
<div className="inpt-cont center">
<p>{this.state.doxaValue}</p>
</div>
<div className="img-cont">
<img src={miniLogo} alt="miniLogo" />
<p>DOXAZO</p>
</div>
</div>
{/* btn */}
<button className="bs-btn" disabled={this.state.loading} onClick={() => this.props.wallet.connected ? this.buyToken() : this.connectToWallet()}>{this.props.wallet.connected ? this.state.loading ?
<span>Processing <img src={buyLoader}></img></span>
: 'Buy' : 'PROCEED TO SWAP'}</button>
</div>
</div>
);
}
}
const mapStateToProps = state => ({
wallet: state.walletConnect
});
export default connect(mapStateToProps, { connectWallet })(Buydoxa);
My Wallet Action.js Codes:
// constants
import Web3 from "web3";
import Web3Modal from "web3modal";
import WalletConnectProvider from "#walletconnect/web3-provider";
import contract from "../contracts/staking.json";
import tokenContract from "../contracts/token.json";
import walletContract from "../contracts/wallet.json";
import store from './store';
const connectRequest = () => {
return {
type: "CONNECTION_REQUEST",
};
};
export const disconnectRequest = () => {
return {
type: "DISCONNECT"
};
}
export const connectSuccess = (payload) => {
return {
type: "CONNECTION_SUCCESS",
payload: payload,
};
};
const connectFailed = (payload) => {
return {
type: "CONNECTION_FAILED",
payload: payload,
};
};
export const updateAccountRequest = (payload) => {
return {
type: "UPDATE_ADDRESS",
payload: payload,
};
};
const getProviderOptions = () => {
const providerOptions = {
walletconnect: {
package: WalletConnectProvider,
options: {
rpc: {
5: "https://goerli.infura.io/v3/ea95b0776037479abf7a62fc14b55188",
1: "https://mainnet.infura.io/v3/ea95b0776037479abf7a62fc14b55188"
}
}
},
}
return providerOptions;
}
export const connectWallet = () => {
return async(dispatch) => {
dispatch(connectRequest());
try {
const web3Modal = new Web3Modal({
cacheProvider: true,
providerOptions: getProviderOptions() // required
});
const provider = await web3Modal.connect();
const stakingContractAddress = process.env.REACT_APP_DOXACONTRACT_ADDRESS;
const internalWalletAddress = process.env.REACT_APP_WALLET_ADDRESS;
const TokencontractAddress = process.env.REACT_APP_TOKEN_ADDRESS;
await subscribeProvider(provider, dispatch);
const web3 = new Web3(provider);
web3.eth.extend({
methods: [
{
name: "chainId",
call: "eth_chainId",
outputFormatter: web3.utils.hexToNumber
}
]
});
const accounts = await web3.eth.getAccounts();
const address = accounts[0];
const instance = new web3.eth.Contract(
contract,
stakingContractAddress
);
const tokenInstance = new web3.eth.Contract(
tokenContract,
TokencontractAddress
)
const walletInstance = new web3.eth.Contract(
walletContract,
internalWalletAddress
)
if(window.ethereum && window.ethereum.networkVersion !== '5') {
await addNetwork(5);
}
dispatch(
connectSuccess({
address,
web3,
staking: instance,
token: tokenInstance,
wallet: walletInstance,
provider,
connected: true,
web3Modal
})
);
} catch (e) {
dispatch(connectFailed(e));
}
}
}
export const disconnect = () => {
return async(dispatch)=> {
const { web3Modal } = store.getState().walletConnect;
console.log(web3Modal);
web3Modal.clearCachedProvider();
dispatch(disconnectRequest());
}
}
const subscribeProvider = async(provider) => {
if (!provider.on) {
return;
}
provider.on('connect', async(id) => {
console.log(id);
});
provider.on("networkChanged", async (networkId) => {
if(networkId !== '5') {
console.log(networkId);
await store.dispatch(connectFailed('Please switch to Ethereum mainnet'));
addNetwork(5);
} else {
store.dispatch(connectWallet());
}
});
}
export async function addNetwork(id) {
let networkData;
switch (id) {
//bsctestnet
case 5:
networkData = [
{
chainId: "0x4",
},
];
break;
//bscmainet
case 1:
networkData = [
{
chainId: "0x1",
},
];
break;
default:
break;
}
return window.ethereum.request({
method: "wallet_switchEthereumChain",
params: networkData,
});
}
(() => {
if(window.ethereum) {
window.ethereum.on('networkChanged', async function(networkId){
console.log('network change', networkId);
if(networkId !== '5') {
console.log(networkId);
await store.dispatch(connectFailed('Please switch to Binance mainnet'));
addNetwork(5);
} else {
store.dispatch(connectWallet());
}
});
}
})();
The following are the contract and wallet addresses for my Goerli deployments:
Token Address: https://goerli.etherscan.io/address/0x0f0283E1aC1f465cE2076a1F57EA0f1BAb4DDC21
Wallet Address Proxy: https://goerli.etherscan.io/address/0xdF6046711651AEC0d686F12Ed0039d5aC45517f3
The following are the contract and wallet addresses for the previous developer's Rinkeby deployments:
Token deployed by other developer on Rinkeby network: https://rinkeby.etherscan.io/address/0xD99b4BB049a6Dd490901CDfa33F15C4fAc097EF0
The wallet proxy deployed on Rinkeby: https://rinkeby.etherscan.io/address/0x5309E16fc58Dc900a08d92BE6559758D692f39Bb

Related

How can I password protect every page in NextJS and Supabase, using the Supabase default auth helpers and UI?

I'm trying to add user authentication to every page in my NextJS project (pages, not app.) This tutorial was very helpful (and is exactly what I want to do) - https://alexsidorenko.com/blog/next-js-protected-routes/ - but I'm having trouble integrating Supabase's default auth UI and capabilities into that model (https://supabase.com/docs/guides/auth/auth-helpers/nextjs).
My basic goal is to move authentication branching into _app.tsx, rather than on each page:
// _app.tsx
import { useEffect, useState } from "react";
import { createBrowserSupabaseClient } from '#supabase/auth-helpers-nextjs'
import { SessionContextProvider, useUser, useSession, useSupabaseClient, Session } from '#supabase/auth-helpers-react'
import { Auth, ThemeSupa } from '#supabase/auth-ui-react'
import { AppProps } from 'next/app'
import { UserContext } from "#components/user"
function MyApp({Component, pageProps}: AppProps<{ initialSession: Session }>) {
const [supabase] = useState(() => createBrowserSupabaseClient())
const session = useSession()
const user = useUser()
console.log("session:" + session);
console.log("user:" + user);
useEffect(() => {
if (
pageProps.protected
) {
return <Auth supabaseClient={supabase} appearance={{ theme: ThemeSupa }} theme="dark" />
}
}, [])
return (
<SessionContextProvider supabaseClient={supabase} session={session} initialSession={pageProps.initialSession}>
<Component {...pageProps} />
</SessionContextProvider>
)
}
export default MyApp
A page I want to protect (for example, the index page) looks like this:
// index.tsx
import Account from "#components/account";
const Home = () => {
return (
<div>
<Account session={session} />
</div>
)
}
export async function getStaticProps(context) {
return {
props: {
protected: true,
},
}
}
export default Home
And then the Account component that's included on the index page is the Supabase out of the box profile panel, although it could be any content:
// #components/account.tsx
import { useState, useEffect } from 'react'
import { useUser, useSupabaseClient, Session } from '#supabase/auth-helpers-react'
import { Database } from '#utils/database.types'
type Profiles = Database['public']['Tables']['profiles']['Row']
export default function Account({ session }: { session: Session }) {
const supabase = useSupabaseClient<Database>()
const user = useUser()
const [loading, setLoading] = useState(true)
const [username, setUsername] = useState<Profiles['username']>(null)
useEffect(() => {
getProfile()
}, [session])
async function getProfile() {
try {
setLoading(true)
if (!user) throw new Error('No user')
let { data, error, status } = await supabase
.from('profiles')
.select(`username`)
.eq('id', user.id)
.single()
if (error && status !== 406) {
throw error
}
if (data) {
setUsername(data.username)
}
} catch (error) {
alert('Error loading user data!')
console.log(error)
} finally {
setLoading(false)
}
}
async function updateProfile({
username,
}: {
username: Profiles['username']
}) {
try {
setLoading(true)
if (!user) throw new Error('No user')
const updates = {
id: user.id,
username,
updated_at: new Date().toISOString(),
}
let { error } = await supabase.from('profiles').upsert(updates)
if (error) throw error
alert('Profile updated!')
} catch (error) {
alert('Error updating the data!')
console.log(error)
} finally {
setLoading(false)
}
}
return (
<div>
<div>
<label htmlFor="email">Email</label>
<input id="email" type="text" value={session.user.email} disabled />
</div>
<div>
<label htmlFor="username">Username</label>
<input id="username" type="text" value={username || ''} onChange={(e) => setUsername(e.target.value)} />
</div>
<div>
<button onClick={() => updateProfile({ username })} disabled={loading} >
{loading ? 'Loading ...' : 'Update'}
</button>
</div>
<div>
<button onClick={() => supabase.auth.signOut()}>
Sign Out
</button>
</div>
</div>
)
}
I think I have a fundamental misunderstanding of the relationship between protected routes and Supabase's use of session and user.
Any help would be very much appreciated.
I'd recommend using Next.js middleware for this: https://supabase.com/docs/guides/auth/auth-helpers/nextjs#auth-with-nextjs-middleware
import { createMiddlewareSupabaseClient } from '#supabase/auth-helpers-nextjs'
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
export async function middleware(req: NextRequest) {
// We need to create a response and hand it to the supabase client to be able to modify the response headers.
const res = NextResponse.next()
// Create authenticated Supabase Client.
const supabase = createMiddlewareSupabaseClient({ req, res })
// Check if we have a session
const {
data: { session },
} = await supabase.auth.getSession()
// Check auth condition
if (session?.user.email?.endsWith('#gmail.com')) {
// Authentication successful, forward request to protected route.
return res
}
// Auth condition not met, redirect to home page.
const redirectUrl = req.nextUrl.clone()
redirectUrl.pathname = '/'
redirectUrl.searchParams.set(`redirectedFrom`, req.nextUrl.pathname)
return NextResponse.redirect(redirectUrl)
}
export const config = {
matcher: '/middleware-protected/:path*',
}

How to access request data in layouts and pages in Qwik City

I'm creating an application Qwik and Qwik City.
I want to show something in my layout, only if it's the home page.
This is my layout.jsx:
const Layout = component$((props) => {
// console.log(props); // I don't see anything related to request
const isHomePage = true; // how can I know I'm inside the home page?
return <>
{isHomePage && <TopBar />}
</>
})
import { component$, Slot } from "#builder.io/qwik";
import { loader$, useLocation } from "#builder.io/qwik-city";
export const useUser = loader$(async ({ fail }) => {
try {
const res = await fetch("https://api.github.com/users/harshmangalam");
const user = await res.json();
return {
user,
};
} catch (error) {
return fail(500, {
error: "Something went wrong",
});
}
});
export default component$(() => {
const user = useUser();
const {
url: { pathname },
} = useLocation();
const isHomePage = pathname === "/";
return (
<div>
{isHomePage && <pre>{JSON.stringify(user.value, null, 4)}</pre>}
<Slot />
</div>
);
});

Button takes 2 clicks before store update Vue and Pinia

I have been messing around with Vue and trying to learn it. On the first click of the button in LoginForm.vue token and user_data are both null. On the second click it finally gets updated. How can I get the live reactive state of the variables?
I am new to Vue so if there are better common practices please let me know.
store/login.js
import { defineStore } from 'pinia'
import axios from 'axios'
export const useUsers = defineStore('users', {
state: () => ({
token: null,
user_data: null
}),
actions: {
async loginUser(data) {
try {
let response = await axios.post("users/login", data)
// Object.assign(this.token, response.data.token)
this.token = response.data.token
axios.defaults.headers.common['user-token'] = this.token
} catch (error) {
return error
}
},
async logout() {
// Object.assign(this.token, null)
// Object.assign(this.user_data, null)
this.token = null
this.user_data = null
// localStorage.removeItem('user');
delete axios.defaults.headers.common['user-token']
},
async login_and_get_user_data(data) {
axios.post("users/login", data).then(response => {
this.token = response.data.token
axios.defaults.headers.common['user-token'] = this.token
axios.get("users/user").then(response2 => {
this.user_data = response2.data.user
})
})
},
async get_user_data() {
console.log(JSON.parse(localStorage.getItem('user'))['token'])
axios.defaults.headers.common['user-token'] = JSON.parse(localStorage.getItem('user'))['token']
let response = await axios.get("users/user")
// Object.assign(this.user_data, response.data.user)
this.user_data = response.data.user
}
}
})
components/LoginForm.vue
<script>
import { useUsers } from '#/stores/login'
import { mapActions } from 'pinia'
import { storeToRefs } from 'pinia'
import { isProxy, toRaw } from 'vue';
export default {
setup() {
const store = useUsers()
store.$subscribe((mutation, state) => {
localStorage.setItem('user', JSON.stringify(state))
})
},
data() {
return {
email: "",
password: ""
}
},
methods: {
...mapActions(useUsers, ['loginUser']),
...mapActions(useUsers, ['get_user_data']),
...mapActions(useUsers, ['logout']),
on_click() {
var data = new FormData();
data.append('email', this.email);
data.append('password', this.password);
const store = useUsers()
this.loginUser(data)
this.get_user_data()
const { token } = storeToRefs(store)
const { user_data } = storeToRefs(store)
console.log(token.value)
console.log(toRaw(user_data.value))
},
logout_click() {
this.logout().then(
console.log(JSON.parse(localStorage.getItem('user')))
)
}
}
}
</script>
<template>
<input type="email" v-model="email" placeholder="youremail#mail.com">
<br>
<input type="password" v-model="password">
<br>
<button #click="on_click">Submit</button>
<br>
<button #click="logout_click">Logout</button>
</template>
Your method on_click is calling async methods like loginUser or get_user_data without waiting them to be finished.
So by the time your are logging console.log(token.value) your http request is probably not finished yet and your token is still null.
You need to await the methods that are doing those requests.
async on_click() {
var data = new FormData();
data.append('email', this.email);
data.append('password', this.password);
const store = useUsers()
await this.loginUser(data)
await this.get_user_data()
const { token } = storeToRefs(store)
const { user_data } = storeToRefs(store)
console.log(token.value)
console.log(toRaw(user_data.value))
},
Keep in mind that you will probably need to display a loader to give the user a feedback because the on_click is now asynchronous and take a bit more time

How to integrate paypal Payment Button Vuejs3 Composition API (setup function)

I'm trying to integrate PayPal buttons with my Vuejs3 project using Composition API (setup ) but all what i get is errors i try to integrate it without using setup and its working fine i leave the working script down
the esseu is i couldent pass data from data to methodes
<script>
import { inject, onMounted, ref } from "vue";
export default {
data() {
return {
loaded: false,
paidFor: false,
product: {
price: 15.22,
description: "leg lamp from that one movie",
img: "./assets/lamp.jpg",
},
};
},
setup() {
const store = inject("store");
console.log(store.state.prodects_in_cart);
return { store };
},methods:{
setLoaded: function() {
this.loaded = true;
paypal_sdk
.Buttons({
createOrder: (data, actions) => {
return actions.order.create({
purchase_units: [
{
description: this.product.description,
amount: {
currency_code: "USD",
value: this.product.price
}
}
]
});
},
onApprove: async (data, actions) => {
const order = await actions.order.capture();
this.data;
this.paidFor = true;
console.log(order);
},
onError: err => {
console.log(err);
}
})
.render(this.$refs.paypal);
}
},
mounted: function() {
const script = document.createElement("script");
script.setAttribute('data-namespace',"paypal_sdk");
script.src ="https://www.paypal.com/sdk/js?client-id=Here i pute my Client Id";
script.addEventListener("load", this.setLoaded);
document.body.appendChild(script);
},
};
</script>
the error i get when i use setup() is
The error image
my script using setup()
setup() {
const store = inject("store");
const paypal = ref(null);
let loaded = ref(false);
let paidFor = ref(false);
const product = {
price: 15.22,
description: "leg lamp from that one movie",
img: "./assets/lamp.jpg",
};
onMounted: {
const script = document.createElement("script");
script.setAttribute("data-namespace", "paypal_sdk");
script.src =
"https://www.paypal.com/sdk/js?client-id=AXDJPmFjXpXm9HMXK4uZcW3l9XrCL36AxEeWBa4rhV2-xFcVYJrGKvNowY-xf2PitTSkStVNjabZaihe";
script.addEventListener("load", ()=>{
loaded = true;
console.log('hello adil');
paypal_sdk
.Buttons({
createOrder: (data, actions) => {
return actions.order.create({
purchase_units: [
{
description: 'this is product description',
amount: {
currency_code: "USD",
value: 120.00,
},
},
],
});
},
onApprove: async (data, actions) => {
const order = await actions.order.capture();
this.data;
this.paidFor = true;
console.log(order);
},
onError: (err) => {
console.log(err);
},
})
.render(paypal);
});
document.body.appendChild(script);
}
return { store ,paypal};
}
paypal is a ref. You're currently passing to paypal_sdk the ref itself and not the inner value, which would be the template ref's element. To fix this, pass the ref's .value.
Your onMounted code is not properly invoked, as it must be passed a callback.
import { onMounted, ref } from 'vue'
export default {
setup() {
const paypal = ref(null)
onMounted(/* 2 */ () => {
const script = document.createElement('script')
//...
script.addEventListener('load', () => {
paypal_sdk
.Buttons(/*...*/)
.render(paypal.value) /* 1 */
})
})
return {
paypal
}
}
}
The reason why you are getting that error is because you are using option Api onMounted life cycle hook, instead of doing that use the vue 3 life cycle hooks for onMounted.
First you will have to import it from vue like this.
<script>
import {onMounted} from 'vue'
then you are going to use it like this.
return it as a call back function
onMounted(() => {
//all your code should placed inside here and it will work
})
</script>
Here is my answer using the paypal-js npm package
<template>
<div ref="paypalBtn"></div>
</template>
<script>
import { onMounted, ref } from 'vue';
import { loadScript } from '#paypal/paypal-js';
const paypalBtn = ref(null);
onMounted(async () => {
let paypal;
try {
paypal = await loadScript({
'client-id': 'you_client_id_goes_here',
});
} catch (error) {
console.error('failed to load the PayPal JS SDK script', error);
}
if (paypal) {
try {
await paypal.Buttons().render(paypalBtn.value);
} catch (error) {
console.error('failed to render the PayPal Buttons', error);
}
}
});
</script>

BotFramework-WebChat v4: post activity to direct line from the UI to the bot

My WebChat code is based on the React minimizable-web-chat v4.
I want to send a message to the bot when user click the location button.
handleLocationButtonClick function is called and it sends latitude and longitude to the bot.
This is my code:
import React from 'react';
import { createStore, createStyleSet } from 'botframework-webchat';
import WebChat from './WebChat';
import './fabric-icons-inline.css';
import './MinimizableWebChat.css';
export default class extends React.Component{
constructor(props) {
super(props);
this.handleFetchToken = this.handleFetchToken.bind(this);
this.handleMaximizeButtonClick = this.handleMaximizeButtonClick.bind(this);
this.handleMinimizeButtonClick = this.handleMinimizeButtonClick.bind(this);
this.handleSwitchButtonClick = this.handleSwitchButtonClick.bind(this);
this.handleLocationButtonClick = this.handleLocationButtonClick.bind(this);
const store = createStore({}, ({ dispatch }) => next => action => {
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'webchat/join',
}
});
}
else if(action.type === 'DIRECT_LINE/INCOMING_ACTIVITY'){
if (action.payload.activity.name === 'locationRequest') {
this.setState(() => ({
locationRequested: true
}));
}
}
return next(action);
});
this.state = {
minimized: true,
newMessage: false,
locationRequested:false,
side: 'right',
store,
styleSet: createStyleSet({
backgroundColor: 'Transparent'
}),
token: 'token'
};
}
async handleFetchToken() {
if (!this.state.token) {
const res = await fetch('https://webchat-mockbot.azurewebsites.net/directline/token', { method: 'POST' });
const { token } = await res.json();
this.setState(() => ({ token }));
}
}
handleMaximizeButtonClick() {
this.setState(() => ({
minimized: false,
newMessage: false
}));
}
handleMinimizeButtonClick() {
this.setState(() => ({
minimized: true,
newMessage: false
}));
}
handleSwitchButtonClick() {
this.setState(({ side }) => ({
side: side === 'left' ? 'right' : 'left'
}));
}
handleLocationButtonClick(){
var x = document.getElementById("display");
if (navigator.geolocation) {
navigator.geolocation.getCurrentPosition(showPosition);
this.setState(() => ({
locationRequested: false
}));
}
else
{
x.innerHTML = "Geolocation API is not supported by this browser.";
}
function showPosition(position) {
x.innerHTML = "Latitude: " + position.coords.latitude + "<br>Longitude: " + position.coords.longitude;
this.store.dispatch({
type: 'WEB_CHAT/SEND_MESSAGE',
payload: { text: 'latitude:'+position.coords.latitude+'longitude:'+position.coords.longitude }
});
}
}
render() {
const { state: {
minimized,
newMessage,
locationRequested,
side,
store,
styleSet,
token
} } = this;
return (
<div className="minimizable-web-chat">
{
minimized ?
<button
className="maximize"
onClick={ this.handleMaximizeButtonClick }
>
<span className={ token ? 'ms-Icon ms-Icon--MessageFill' : 'ms-Icon ms-Icon--Message' } />
{
newMessage &&
<span className="ms-Icon ms-Icon--CircleShapeSolid red-dot" />
}
</button>
:
<div
className={ side === 'left' ? 'chat-box left' : 'chat-box right' }
>
<header>
<div className="filler" />
<button
className="switch"
onClick={ this.handleSwitchButtonClick }
>
<span className="ms-Icon ms-Icon--Switch" />
</button>
<button
className="minimize"
onClick={ this.handleMinimizeButtonClick }
>
<span className="ms-Icon ms-Icon--ChromeMinimize" />
</button>
</header>
<WebChat
className="react-web-chat"
onFetchToken={ this.handleFetchToken }
store={ store }
styleSet={ styleSet }
token={ token }
/>
{
locationRequested ?
<div>
<p id="display"></p>
<button onClick={this.handleLocationButtonClick}>
Gélolocation
</button>
</div>
:
<div></div>
}
</div>
}
</div>
);
}
}
When I click the button, I have this error:
And in the console:
What is wrong ??
First, there have been some updates to the a.minimizable-web-chat sample that are worth looking over. Refer to the code, however, as the README.md file has not been fully updated to reflect the changes.
As for your question, try the following changes. When tested, it works successfully for me. Change the component to a function and define store via useMem0().
import React, { useCallback, useMemo, useState } from 'react';
const MinimizableWebChat = () => {
const store = useMemo(
() =>
createStore({}, ({ dispatch }) => next => action => {
if (action.type === 'DIRECT_LINE/CONNECT_FULFILLED') {
dispatch({
type: 'WEB_CHAT/SEND_EVENT',
payload: {
name: 'webchat/join',
value: {
language: window.navigator.language
}
}
});
} else if (action.type === 'DIRECT_LINE/INCOMING_ACTIVITY') {
if (action.payload.activity.from.role === 'bot') {
setNewMessage(true);
}
}
return next(action);
}),
[]
);
[...]
return (
[...]
<WebChat
[...]
store={store}
);
}
export default MinimizableWebChat;
Given the changes implemented in this file, it likely will impact how the other files function with it. My recommendation would be to do a wholesale update to bring your project in line with the current sample. It's really just this file, WebChat.js, and possibly App.js. There are supporting CSS files and the like that can be downloaded, if you don't have them.
Hope of help!