Vue3 Reactive value is not updating as expected - javascript

I have this .ts file:
import { reactive, toRefs } from 'vue'
export const TitleComponent = () => {
const obj = reactive({
title: "This should be reactive"
})
const updateObj = () => {
obj.title = 'This is now different'
}
return {...toRefs(obj), updateObj }
}
I then import is into a vue component which DISPLAYS it
<template>
<h1>{{ title }}</h1>
</template>
import { defineComponent } from 'vue'
import { TitleComponent } from 'some/place'
export default defineComponent({
const { title } = TitleComponent()
return { title }
})
Then, I use the function updateObj in another component that runs that method. But it doesn't update the title value. What gives?
<template>
<button #click="updateObj">Click Me</button>
</template>
import { defineComponent } from 'vue'
import { TitleComponent } from 'some/place'
export default defineComponent({
const { updateObj } = TitleComponent()
return { updateObj}
})

Move obj outside of export const TitleComponent = () => {}.
import { reactive, toRefs } from 'vue';
const obj = reactive({
title: 'This should be reactive'
});
export const TitleComponent = () => {
const updateObj = () => {
obj.title = 'This is now different'
};
return { ...toRefs(obj), updateObj };
}
When its inside and you import/call TitleComponent() it creates a new instance of obj every time.

Related

Vue3: why a componment instance template ref unable to find defined function

LoginAccount.vue
<script setup lang="ts">
import { rules } from './config/AccountConfig'
import { reactive } from 'vue'
import { ref } from 'vue';
import { ElForm } from 'element-plus';
const account = reactive({
name: '',
password: ''
})
const formRef = ref<InstanceType<typeof ElForm>>()
const loginAction = () => {
console.log("开始登录")
formRef.value?.validate((valid) => {
if (valid) {
console.log("登录逻辑")
}
})
}
// 规则
</script>
LoginPanel
<script setup lang="ts">
import LoginAccount from './LoginAccount.vue'
import LoginPhone from './LoginPhone.vue'
import { ref } from 'vue'
const isKeepPassword = ref(false);
const accountRef = ref<InstanceType<typeof LoginAccount>>()
const handleLoginClick = () => {
console.log("立即登录")
accountRef.value?.loginAction() No property exists " loginAction"
}
</script>
error
How do I type the imported component, so that when I call its methods through refs, it checks exposed method names and types of passed arguments?
accountRef.value?.loginAction() No property exists " loginAction"
how to solve it?
Docs
Components using <script setup> are closed by default - i.e. the public instance of the component, which is retrieved via template refs or $parent chains, will not expose any of the bindings declared inside <script setup>
To explicitly expose properties in a <script setup> component, use the defineExpose compiler macro
<script setup lang="ts">
import { rules } from './config/AccountConfig'
import { reactive } from 'vue'
import { ref } from 'vue';
import { ElForm } from 'element-plus';
const account = reactive({
name: '',
password: ''
})
const formRef = ref<InstanceType<typeof ElForm>>()
const loginAction = () => {
console.log("开始登录")
formRef.value?.validate((valid) => {
if (valid) {
console.log("登录逻辑")
}
})
}
// 规则
defineExpose({
loginAction,
})
</script>

how to showing result value in react website

i am new in react, how to showing (accountInfo[4]) value in my website?
when i changed to
const setPaid = (accountInfo[4])
TypeError: Cannot read property '4' of undefined
import React, { useState } from 'react';
import useAccountInfo from '../abi/useAccountInfo';
import Value from '../utils/value';
const Hero = () => {
const accountInfo = useAccountInfo();
const setPaid = console.log(accountInfo);
return (
<div>
<Value value={setPaid}/>
</div>
);
export default Hero;
this the result in console
this my useAccountInfo.js file
import { useEffect, useState } from 'react'
import { useWallet } from 'use-wallet'
import { BigNumber } from 'ethers';
import useBlock from './useBlock'
import useTokenInfo from './useTokenInfo';
const useAccountInfo = () => {
const [accountInfo, setAccountInfo] = useState(BigNumber.from(0));
const {account, ethereum} = useWallet();
const block = useBlock();
const tokenInfo = useTokenInfo();
const fetchAccountInfo = async () => {
if (!account) {
setAccountInfo(BigNumber.from(0));
return;
}
const accountInfo = await tokenInfo?.accountInfo();
setAccountInfo(accountInfo);
};
useEffect(() => {
fetchAccountInfo();
}, [block, account, ethereum, tokenInfo]);
return accountInfo;
}
export default useAccountInfo;

Cant pass params id in vuex

Please tell me how instead of {id} when getter call, take its id and insert it into the link with the request in vuex
industry.js
import { INDUSTRY } from '#/utils/store/getters.names.js'
import { FETCH_INDUSTRY } from '#/utils/store/actions.names.js'
import { SET_INDUSTRY, SET_INDUSTRY_ERROR } from '#/utils/store/mutations.names.js'
import { API_ENDPOINT } from '#/utils/store/endpoints.js'
export const state = () => ({
industry: [],
industryError: false
})
export const getters = {
[INDUSTRY]: state => state.industry
}
export const actions = {
[FETCH_INDUSTRY] ({ commit }, id) {
this.$axios.$get(`${API_ENDPOINT}/pages/?child_of=${id}&type=pages.IndustryEquipmentCategoryPage&fields=*`).then((data) => {
commit(SET_INDUSTRY, data)
}).catch((e) => {
commit(SET_INDUSTRY_ERROR)
})
}
}
export const mutations = {
[SET_INDUSTRY] (state, industry) {
state.industryError = false
state.industry = industry
},
[SET_INDUSTRY_ERROR] (state) {
state.industry = []
state.industryError = true
}
}
index.js
import { FETCH_MENU, FETCH_SETTINGS, FETCH_INDUSTRY } from '#/utils/store/actions.names.js'
export const state = () => ({})
export const actions = {
async nuxtServerInit ({ dispatch }) {
dispatch(`menu/${FETCH_MENU}`)
dispatch(`settings/${FETCH_SETTINGS}`)
dispatch(`industry/${FETCH_INDUSTRY}`)
}
}
actions.names.js
export const FETCH_INDUSTRY = 'fetchIndustry'
getters.names.js
export const INDUSTRY = 'industry'
mutations.names.js
export const SET_INDUSTRY = 'setIndustry'
export const SET_INDUSTRY_ERROR = 'SetIndustryError'
i cannot pass id to fetch getter data. how can i pass params id in getters please tell me
IndustryEquipmentIndexPage.vue
<template>
<div class="eqmodel-mainwrap">
</div>
</template>
<script>
import {
Component,
Getter,
Prop,
Action,
Mutation,
Vue,
mixins,
Watch
} from "nuxt-property-decorator";
import { PhCaretRight, PhCaretLeft } from "phosphor-vue";
import { INDUSTRY } from "~/utils/store/getters.names";
import { FETCH_INDUSTRY } from "~/utils/store/actions.names";
import { SET_INDUSTRY,SET_INDUSTRY_ERROR } from "~/utils/store/mutations.names";
import { PAGES_ENDPOINT } from "#/utils/store/endpoints.js";
import { gsap, TimelineMax, Power2, Power1, clearProps } from "gsap/all";
import axios from "axios";
import { directive } from "vue-awesome-swiper";
#Component({
name: "IndustryEquipmentIndexPage",
components: {
PhCaretRight,
PhCaretLeft
}
})
export default class IndustryEquipmentIndexPage extends Vue {
#Prop() pageData;
#Action(FETCH_INDUSTRY) fetchIndustry;
#Mutation(SET_INDUSTRY) setIndustry;
#Getter(`industry/${INDUSTRY}`) industry;
get HOST() {
return process.env.HOST;
}
}
</script>
According to Vue documentation you can do that with method style access.
export const getters = {
[INDUSTRY]: state => (id) => state.industry.find(smthg => smthg.id === id)
}

Why my "mapDispatchToProps" does not see my action function?

Please tell me why, when I call this.props.getOnEvents(), an error occurs that “getOnEvents() is not a function”, what’s wrong here and how to fix it?
I’m looking at the console.log and there is this function in the props, but when I try to call, an error flies out that it’s not a function
EventCalendar.js
import React, { Component } from 'react';
import { withStyles } from '#material-ui/core/styles';
import EventCalendarTable from './EventCalendarTable';
import EventCalendarView from './EventCalendarView';
const styles = theme => ({
root: {
width: '80%',
margin: '20px auto 0'
},
});
class EventCalendar extends Component {
constructor(props) {
super(props);
this.state = {
viewEvents: 'table'
};
}
componentDidMount() {
this.props.onGetEvents();
}
changeEventsView = (value) => {
this.setState({ viewEvents: value });
}
render() {
console.log(this.props);
const { classes } = this.props;
return (
<div className={classes.root}>
<EventCalendarView changeEventsView={this.changeEventsView}/>
{
this.state.viewEvents === 'table'
? <EventCalendarTable />
: <div>test</div>
}
</div>
);
}
}
export default withStyles(styles)(EventCalendar);
EventPage/component.jsx
import React from 'react';
import EventCalendar from '../../components/EventCalendar';
import './index.scss';
function Events(props) {
return (
<React.Fragment>
<EventCalendar props={props}/>
</React.Fragment>
);
}
export default Events;
EventPage/container.js
import { connect } from 'react-redux';
import EventsPage from './component';
import { getEvents } from '../../../store/modules/Events/operations';
const mapStateToProps = ({ Events }) => ({
Events
});
const mapDispatchToProps = dispatch => ({
onGetEvents: () => {
console.log(123);
dispatch(getEvents());
}
});
export default connect(
mapStateToProps,
mapDispatchToProps
)(EventsPage);
Events/actions.js
import * as types from './types';
export const eventsFetch = value => ({
type: types.FETCHING_EVENTS,
payload: value
});
export const setEvents = ({ objById, arrayIds }) => ({
type: types.SET_EVENTS,
payload: {
eventById: objById,
eventsOrder: arrayIds
}
});
Events/types.js
export const FETCHING_EVENTS = 'Events/FETCHING_EVENTS';
export const SET_EVENTS = 'Events/SET_EVENTS';
Events/operation.js
import FetchClient from 'app/utils/FetchClient';
import IdsAndByIds from 'app/utils/IdsAndByIds';
import { eventsFetch, setEvents } from './actions';
export const getEvents = () => async (dispatch) => {
try {
const { data } = await FetchClient.get('/events');
dispatch(setEvents(IdsAndByIds(data)));
dispatch(eventsFetch(false));
} catch (error) {
console.log(error);
}
};
Events/reducer.js
import { createReducer } from 'store/utils';
import * as types from './types';
const usersInitState = {
fetching: true,
events: {
eventById: null,
usersOrder: null
},
error: null
};
const eventsReducer = createReducer(usersInitState)({
[types.FETCHING_EVENTS]: (state, { payload }) => ({
...state,
fetching: payload
}),
[types.SET_EVENTS]: (state, { payload }) => ({
...state,
events: {
...payload
}
})
});
export default eventsReducer;
Events/index.js
import { combineReducers } from 'redux';
import * as eventsListOperations from './operations';
import reducer from './reducers';
const EventsReducer = combineReducers({
eventsList: reducer
});
export default EventsReducer;
export { eventsListOperations };
The issue here is a minor one, Since you are connecting Events component to connect, you are receiveing the prop onGetEvents in that component, Now inside this component you are passing the props by a name props to the EventCalendar component
<EventCalendar props={props}/>
Now the props in EventCalender will contain a key called as props which wil lhave your data but you are trying to access it directly on props which is why it is undefined.
The correct way to pass the props here would be to use spread syntax like
<EventCalendar {...props}/>

Getting 'dispatch is not defined' in redux component

I am trying to get a list of names stored in firebase to save to the redux store when the component loads. This list then gets sent to a dropdown component as props which are rendered as selectable options in the dropdown. For some reason I am getting 'dispatch is not defined' and I am not sure how to fix.
This is my code:
//store
import * as redux from 'redux';
import thunk from 'redux-thunk';
import {userReducer, exampleReducer, namesReducer} from 'reducers';
export var configure = (initialState = {}) => {
const reducer = redux.combineReducers({
user: userReducer,
example: exampleReducer,
names: namesReducer
})
var store = redux.createStore(reducer, initialState, redux.compose(
redux.applyMiddleware(thunk),
window.devToolsExtension ? window.devToolsExtension() : f => f
));
return store;
};
//reducers
export var namesReducer = (state = [], action) => {
switch (action.type) {
case 'GET_NAMES':
return [
action.names
]
default:
return state;
}
}
//actions
export var getNames = (names) => {
return {
type: 'GET_NAMES',
names
}
};
export var startGetNames = () => {
console.log("action started")
return (dispatch) => {
var nameRef = firebase.database().ref().child('names');
return nameRef.once('value').then((snapshot) => {
var data = snapshot.val();
_.map(data, function(name) {return finalArr.push(
{
display: `${name.first_name} ${name.last_name}`,
value: name.id
}
)});
dispatch(getNames(finalArr));
})
}
}
//component
import _ from 'underscore';
import React from 'react';
import { render } from "react-dom";
import {connect} from 'react-redux';
import Modal from 'react-responsive-modal';
var actions = require('actions');
var firebase = require('firebase/app');
require('firebase/auth');
require('firebase/database');
//components
import roomBookingForm from 'roomBookingForm';
import PanelHeader from 'PanelHeader';
import PanelItem from 'PanelItem';
import Table from 'Table';
import TableRow from 'TableRow';
import TableHeaderCell from 'TableHeaderCell';
import TextInput from 'TextInput';
import Dropdown from 'Dropdown';
class roomBooking extends React.Component {
constructor(props) {
super(props);
this.state = {
pageTitle: "Appointment Creation",
openForm: false
}
}
componentWillMount() {
this.props.clinicians
}
onOpenModal = () => {
this.setState({openForm: true});
}
modalClose = () => {
this.setState({ openForm: false });
};
render() {
return (
<div className="main-container">
<div className="options-menu">
<PanelHeader >
Options
</PanelHeader>
<PanelItem onClick={this.onOpenModal} propClassLeft="left-item" propClassRight="right-item">Create Appointment</PanelItem>
</div>
<div>
<Table className="display-table">
<TableRow className="display-table-head">
<TableHeaderCell className="name" displayText="Name" />
</TableRow>
</Table>
</div>
<roomBookingForm open={this.state.openForm} onClose={this.modalClose} options={this.props.names} />
</div>
)
}
}
const mapDispatchToProps = (dispatch) => {
names : dispatch(actions.startGetNames())
}
export default connect()(roomBooking);
You have two correction in your code.
1.
You need to pass mapDispatchToProps in the connect call.
const mapDispatchToProps = (dispatch) => {
names : dispatch(actions.startGetNames())
}
export default connect(null,mapDispatchToProps)(roomBooking);
2.To call asynchronous action method with react-redux,the right signature is :
export var startGetNames = () => (dispatch) => {
return (dispatch) => {
//code
}
}
There are few issues with your code:
finalArr is not defined before using it.
dispatch does not work like this. It needs to be called like store.dispatch({ACTION}). So, you'll need to import store.
you should pass mapDisPatchToProps to connect function:
const mapDispatchToProps = (dispatch) => {
names : dispatch(actions.startGetNames())
}
export default connect(function(){},mapDispatchToProps)(roomBooking);

Categories

Resources