emit in fuction in vue 3 composition api - vuejs3

I have a timer, and a function by which the timer stops. I want to use emit in a function, it doesn't work.
const stopTimer = () => {
clearInterval(timer.value);
const emit = defineEmits(["end"]);
emit("end", reactionTime.value);
};

defineEmits should be called top-level in <script setup> and not inside any arrow function.

Related

Calling a helper function requiring dispatch from thunk

I'm using Redux Toolkit, though I don't think that makes a difference.
I've set up a snackbar that reads from store.data.message, and I write the message by setting a value and then clearing the message after a timeout. This happens in a helper function, showMessage.
I call showMessage from my thunks:
export const showMessage = (dispatch: any, message: string) => {
dispatch(setMessage(message))
setTimeout(() => dispatch(clearMessage()), 3000)
}
export const fetchDataState = (): AppThunk => async dispatch => {
const state = await getSystemState()
showMessage(dispatch, 'Fetched system state.')
dispatch(getStateSucceeded(state))
}
I simply want to know if there is a way to write these without having to pass dispatch in every time I call showMessage.
Correct me if I'm wrong, but I imagine I can't write it like a thunk because redux-thunk is middleware that calls the thunks in its own way, and I'm not calling them that way.
Yes, you can write it as a thunk like this:
export const showMessage = (message: string) => (dispatch: AppDispatch) => {
dispatch(setMessage(message))
setTimeout(() => dispatch(clearMessage()), 3000)
}
// call it:
dispatch(showMessage("Hi!"))

Testing a Redux action that dispatches 2 other functions with Jest?

I have a function (a Redux action) which calls 2 functions. I can't figure how how to test this with Jest:
This is my function:
import doSomething from 'redux/do-something';
import doSomethingElse from 'redux/do-something-else';
export default () => async dispatch => {
await dispatch(doSomething());
dispatch(doSomethingElse());
};
This is my test:
import doSomething from 'redux/do-something';
import doSomethingElse from 'redux/do-something-else';
import functionToTest from 'redux/function-to-test'
describe("functionToTest", ()=>{
jest.mock('redux/do-something');
jest.mock('redux/do-something-else');
const dispatch = jest.fn();
test('my test', ()=>{
functionToTest()(dispatch);
console.log(dispatch.mock.calls); // This returns an anonymous function
console.log(doSomething) // This returns undefined
})
})
It looks like you are wanting to mock the default export for do-something and do-something-else and test that they get dispatched by the code under test.
If that is the case then you can do it like this:
import functionToTest from 'redux/function-to-test'
jest.mock('redux/do-something', () =>
() => 'do something mock'
);
jest.mock('redux/do-something-else', () =>
() => 'do something else mock'
);
describe("functionToTest", () => {
test('my test', async () => { // <= async test function
const dispatch = jest.fn();
await functionToTest()(dispatch); // <= await the Promise
expect(dispatch.mock.calls[0][0]).toBe('do something mock'); // Success!
expect(dispatch.mock.calls[1][0]).toBe('do something else mock'); // Success!
});
});
Details
You can pass a module factory function as the second paramter to jest.mock and Jest will use the result of calling the function as what it gives back when the module is imported during the test.
jest.mock calls get hoisted by babel-jest and run before everything else in the code file. The hoisting doesn't work right when jest.mock is defined in a test function so the jest.mock calls should be moved to the top level scope of the test file.
The function under test is async so use an async test function and await the Promise to make sure it has completed before asserting.

using bindActionCreators, this.props.dispatch in react-redux disptach vs redux

I've read about bindActionCreators, i've compiled a resumen here:
import { addTodo,deleteTodo } from './actionCreators'
import { bindActionCreators } from 'redux'
function mapStateToProps(state) {
return { todos: state.todos }
}
function mapDispatchToProps(dispatch) {
return bindActionCreators({ addTodo, deleteTodo }, dispatch)
}
*short way
const mapDispatchToProps = {
addTodo,
deleteTodo
}
export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)
another code use like this:
function mapDispatchToProps(dispatch) {
let actions = bindActionCreators({ getApplications });
return { ...actions, dispatch };
}
why previous code with bindActionCreators , don't need disptach parameter?
i've tried this way to get dispatch on this.props (but not working):
const mapDispatchToProps = (dispatch) => {
return bindActionCreators ({ appSubmitStart, appSubmitStop}, dispatch );
};
const withState = connect(
null ,
mapDispatchToProps,
)(withGraphqlandRouter);
why I had to change my old short way:
const withState = connect(
null ,
{ appSubmitStart, appSubmitStop}
)(withGraphqlandRouter);
in order to get this.props.dispatch()? because i neede to use dispatch for an isolated action creator inside a library with js functions. I mean before I don't needed use "bindActionCreators", reading this doc:
https://redux.js.org/api-reference/bindactioncreators
"The only use case for bindActionCreators is when you want to pass some action creators down to a component that isn't aware of Redux, and you don't want to pass dispatch or the Redux store to it."
I'm importing:
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
what is the difference using redux pure, and react-redux?
really I need "bindActionCreators" in my new code? because without this i can't see this.props.dispatch()
UPDATE:
I've found this solutions to get this.props.dispatch working:
const mapDispatchToProps = (dispatch) => {
return bindActionCreators ({ appSubmitStart, appSubmitStop, dispatch }, dispatch ); // to set this.props.dispatch
};
does anyone can explain me? how i can send same distpach like a creator ?
First let's clear our minds regarding some of the key concepts here:
bindActionCreators is a util provided by Redux. It wraps each action creators to a dispatch call so they may be invoked directly.
dispatch is a function of the Redux store. It is used to dispatch actions to store.
When you use the object shorthand for mapState, React-Redux wraps them with the store's dispatch using Redux's bindActionCreators.
connect is a function provided by React-Redux. It is used to connect your component to the Redux store. When you connect your component:
It injects dispatch to your component only if you do not provide your customized mapDispatchToProps parameter.
Regarding what happened above to your code:
Component will not receive dispatch with customized mapDispatchToProps
In the code here:
const mapDispatchToProps = (dispatch) => {
return bindActionCreators(
{ appSubmitStart, appSubmitStop, dispatch }, // a bit problematic here, explained later
dispatch
); // to set this.props.dispatch
};
You are providing your own mapDispatch, therefore your component will not receive dispatch. Instead, it will rely on your returned object to contain the action creators wrapped around by dispatch.
As you may feel it is easy to make mistake here. It is suggested that you use the object shorthand directly, feeding in all the action creators your component will need. React-Redux binds each one of those with dispatch for you, and do not give dispatch anymore. (See this issue for more discussion.)
Writing customized mapState and inject dispatch manually
However, if you do need dispatch specifically alongside other action dispatchers, you will need to define your mapDispatch this way:
const mapDispatchToProps = (dispatch) => {
return {
appSubmitStart: () => dispatch(appSubmitStart),
appSubmitStop: () => dispatch(appSubmitStop),
dispatch,
};
};
Using bindActionCreators
This is exactly what bindActionCreators does. Therefore, you can simplify a bit by using Redux's bindActionCreators:
const mapDispatchToProps = (dispatch) => {
return bindActionCreators(
{ appSubmitStart, appSubmitStop }, // do not include dispatch here
dispatch
);
};
As mentioned above, the problem to include dispatch in the first argument is that it essentially gets it wrapped around by dispatch. You will be calling dispatch(dispatch) when you call this.props.dispatch.
However, bindActionCreators does not return the object with dispatch. It's passed in for it to be called internally, it does not give it back to you. So you will need to include that by yourself:
const mapDispatchToProps = (dispatch) => {
return {
...bindActionCreators({appSubmitStart, appSubmitStop}, dispatch),
dispatch
};
};
Hope it helped! And please let me know if anything here is unclear :)
I have made some changes to your code please try this
import * as Actions from './actionCreators'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
const mapStateToProps = (state)=>(
{
todos: state.todos
}
)
const mapDispatchToProps = (dispatch)=> (
bindActionCreators(Actions, dispatch)
)
export default connect(mapStateToProps, mapDispatchToProps)(TodoApp)

How can i test arrow function in mapDispatchToProps of redux by jest

How can I test two simple actions in mapDispatchToProps of my component.
Command for tests that i'm using is jest --coverage, and it tells me to test next lines of my code:
export const mapDispatchToProps = (dispatch) => {
return {
----> rightText: () => dispatch(rightText()),
----> leftText: () => dispatch(leftText()),
};
};
How can I write tests to cover these two arrow functions inside mapDispatchToProps?
I think the easiest way is to pass a spy to mapDispatchToProps and then you can test the functions of returned object:
const actionProps = mapDispatchToProps(spy)
// now you can test them
actionProps.rightText()
actionProps.leftText()
rightText() and leftText() should return an object (if it's synchronous). You can also verify the action object in your spy (or it's a mock here) function.
const mockDispatch = jest.fn()
const actionProps = mapDispatchToProps(mockDispatch)
actionProps.rightText()
actionProps.leftText()
// now you can verify the actions here
mockDispatch.mock.calls[0][0]
mockDispatch.mock.calls[1][0]
And just let you know, you can pass a plain object to connect. In your case you can simply:
connect(mapStateToProps, {
rightText,
leftText
})(Component)

Redux Saga - call "yield put" inside async callback

Inside my saga, I am calling an async function and passing it a callback. The reason I am passing it a callback is because it can be called a few times from the async function.
How can I call "yield put" from inside the callback which should be called more than one time from inside the async function.
As you have noticed, there is no way to yield inside a nested function of your generator function. Instead you can convert the callback style async function into a promise, and use the call effect.
function* generator() {
const results = yield call(function() {
return new Promise(function(resolve, reject) {
const results = [];
asyncFunction(function(result) {
if (async function is done) { resolve(results) }
else { results.push(result) }
});
});
});
yield put(action(results));
}
This is a common pattern, but the tricky part for you will be knowing when asyncFunction has completed. It will need some way to signal that it has called the callback function for the last time.

Resources