I want to dispatch outside component. I want to use option 2 from this link [https://daveceddia.com/access-redux-store-outside-react/][1]. My code look like this
const loginUser = async (data) => {
return axios.get(url + "/sanctum/csrf-cookie").then(() => {
axios.post(url + '/api/login', data)
.then(res => {
return res.data
})
.catch((err) => {
console.log(err);
})
})
}
export const handleLogin = (data) => async (dispatch) => {
console.log('test');
try {
const user = await loginUser(data);
dispatch(actions.setUser(user));
} catch (err) {
console.log(err);
}
}
And into my component
const test = (e) => {
e.preventDefault;
handleLogin({email: 'test#test.pl', password: 'password'})
}
return (
<div className="container">
<h2>Login</h2>
<form onSubmit={handleSubmit(test)}>
//...
It doesn't finish code and it may contain mistakes but currently the most important for me is why this code doesn't work and if sometimes is wrong why doesn't show any error. I think that problem is in sync(dispatch). In this example I add console.log for test and it wasn't display. Without that function display console.log.
Redux thunk is added to the store too
const store = createStore(allReducers, composeWithDevTools(applyMiddleware(thunk)))
import store and use like this :
store.dispatch(actions.setUser(user));
and you can get state out of component with :
store.getState().items
you did not dispatch your actions in your component and in your action js .
you can call an action in component by props and dispatch and I could not see the props so I use useDispatch and call handleLogin action there.
use this in action.js file:
const user = await loginUser(data)(dispatch);
instead :
const user = await loginUser(data);
then in component:
import {useDispatch} from "react-redux";
const dispatch = useDispatch();
const test = (e) => {
e.preventDefault;
dispatch(handleLogin({email: 'test#test.pl', password: 'password'}))
}
Related
I am trying to log something to my console on page load in react. I've never really used react and I've only done node.js before, so this is new to me.
I have this so far, but it doesn't seem to be working. It seems more js then react.
window.onload(console.log("logging this here"))
how would I do this?
more code on page:
class NormalLoginForm extends React.Component {
state = {
error: null,
}
handleSubmit = (e) => {
e.preventDefault();
this.props.form.validateFields((err, values) => {
if (err) return
const email = this.props.form.getFieldValue('email')
const password = this.props.form.getFieldValue('password')
var accountStatus1 = ""
AuthorizationHome.doSignInWithEmailAndPassword(email, password)
.then(() => {
firebase.auth().onAuthStateChanged((user) => {
// window.onload(function (console.log("hello"))
For class component you can use;
ComponentDidMount(){
console.log("logging this here")
}
for functional components you can use;
useEffect(() => {
console.log("logging this here")
}, [])
it is impossible this way.
React component will render after window load event. So code will never trigger callback.
U need to change logic and just execute a callback if u want to call something in the component.
some example:
const ComponentWithAuth = () => {
const [user, setUser] = useState(null);
useEffect(() => {
getAuthUser().then(setUser)
});
if (user) {
return <PrivateComponent/>
}
return <LoginForm setUser={setUser}/>
}
const LoginForm = ({setUser) => {
const handleSubmit =async () => {
...
const user =await getAuthUser();
setUser(user);
}
...
}
This is my file for action creators in my react app.
Inside my async getHomePage action I am trying to call setLoading() action which is not getting called. When I comment my code below in my try block and only keep setLoading() then it works and I can see setLoading called in redux dev tools. But when I keep my whole code it gives me SET_HOME and not SET_LOADING.
Is there something I am doing wrong by calling another action from async action.
import axios from '../axios/default.instance';
import {
SET_LOADING,
SET_HOME
} from './types';
export const getHomePage = () => async dispatch => {
try {
setLoading();
const result = await axios.get("/home");
dispatch({
type:SET_HOME,
payload: result.data
});
} catch (error) {
console.log(error);
}
};
export const setLoading = () => {
return {
type: SET_LOADING
}
}
I am learning react-redux async actions with redux-thunk, I would like to fetch data from API (my local database), Unfortunately fetching data with redux-thunk middleware data is not fetched but without thunk middleware data is fetched.
So here are action creators with thunk middleware, which is not working
// retriev comments
export const fetchComments= () =>{
return dispatch =>{
dispatch(fetchCommentsRequest);
axios.get('/api/v1/todo')
.then(response =>{
const comments =response.data;
dispatch(fetchCommentsSucces(comments))
})
.catch(error =>{
const erroMsg =errors.messages
dispatch(fetchCommentsFailure(error))
})
}
}
And here is console log result :
Here is a component where I am calling the function to fetch data from API,
import React, {useEffect}from 'react'
import { fetchComments} from '../store/actions'
import { connect } from "react-redux";
function Dashboard(userComments) {
useEffect(() =>{
fetchComments();
}, [])
return (
<div>
<p>Fetching data</p>
</div>
)
}
const mapStateToProps = state => {
console.log("I am state", state);
return {
isAuthenticated: state.Auth.isAuthenticated,
user: state.Auth.user,
userComments: state.comments
};
};
const mapDispatchToProps = dispatch => {
return {
fetchComments: () => dispatch(fetchComments()),
};
};
export default connect(mapStateToProps, mapDispatchToProps)(Dashboard);
The whole store can be found here: store
Can someone tells me why data is not fetched?
There is an issue with how fetchComments method is called inside the <Dashboard> component.
Once a React component is connected to a Redux store, the data from the store (mapStateToProps) and the functions it can use to dispatch actions to the store (mapDispatchToProps) are passed to that component as an object.
The <Dashboard> component receives this props object that can be accessed inside it like:
function Dashboard(props) {
useEffect(() =>{
props.fetchComments();
}, [])
return (
<div>
<p>Fetching data</p>
</div>
)
}
or using destructuring:
function Dashboard({ isAuthenticated, user, userComments, fetchComments }) {
useEffect(() =>{
fetchComments();
}, [])
return (
<div>
<p>Fetching data</p>
</div>
)
}
In your thunk, dispatch the action properly i.e. call the fetchCommentsRequest function (you are providing reference)
export const fetchComments= () =>{
return dispatch =>{
dispatch(fetchCommentsRequest()); //<-----call the fuction
axios.get('/api/v1/todo')
.then(response =>{
const comments =response.data;
dispatch(fetchCommentsSucces(comments))
})
.catch(error =>{
const erroMsg =errors.messages
dispatch(fetchCommentsFailure(error))
})
}
}
In your repo, the fetchCommentsSucces needs to take an argument.
export function fetchCommentsSucces(comments){ //<----pass argument i.e comments
console.log('success')
return{
type: ActionTypes.FETCH_COMMENTS_SUCCESS,
payload: comments //<----provide correct payload
}
}
Need help in getting response from a function written inside reducer function
functional component
import {
getAssets,
} from '../../reducers';
const myFunctionalComponent = (props) => {
const dispatch = useDispatch();
const onLinkClick = () => {
dispatch(getAssets());
}
}
return (
<div>
<mainContent />
</div>
)
}
In my reducer
const reducer = (state = initialState, action) => {
switch (action.type) {
case ASSETS_LIST: {
return {
...state,
successToast: true,
isLoading: false,
data: action.payload,
};
}
}
export const listsDispactcher = () => dispatch => {
dispatch({ type: SHOW_LOADER });
performGet(ENDPOINT URL)
.then(response => {
debugger;
const payload = response.data;
dispatch({
type: ASSETS_LIST,
payload: {
...payload,
data: payload.results,
},
});
dispatch({ type: HIDE_LOADER });
})
.catch(err => {
dispatch({ type: GET_ASSETS_ERROR, payload: err });
);
});
};
when i click the link ,am getting my api called in function in reducer and its getting response in newtwork tab in developer console , but how to get the response (that is successToast,data,isLoading )in my functional component and to pass the same to child components ?
I advice you to change the structure of your project. Place all your network calls in a file and call them from your component. It is better for readability and understandability
import {
getAssets,
} from './actions';
const myFunctionalComponent = (props) => {
const dispatch = useDispatch();
const onLinkClick = async () => {
const data = await dispatch(getAssets());
}
}
return (
<div>
<mainContent />
</div>
)
}
In ./actions.js
const getAssets =()=>async dispatch =>{
const res = await axios.get();
dispatch(setYourReduxState(res.data));
return res.data;
}
Now your component will get the data of network call. and Your redux state also will get update
For functional components, to access state stored centrally in redux you need to use useSelector hook from react-redux
import React from 'react'
import { useSelector } from 'react-redux'
export const CounterComponent = () => {
const counter = useSelector(state => state.counter)
return <div>{counter}</div>
}
Official doc:
https://react-redux.js.org/api/hooks#useselector-examples
Also found this working example for you to refer.
https://codesandbox.io/s/8l0sv
My thunk action doesn't seem to be running through its core logic. I tall the thunk action from componentDidMount but it doesn't in turn cause this to run: const response = await findOne(id).
Also, I thought I didn't need to explicitely pass dispatch as a prop to mapDispatchToProps if using redux-thunk, I thought that the way I have my thunk setup is that dispatch is available already to the thunk? And I've used other actions like this and it's worked fine, why not this one?
Thunk Action
export function fetchCompany(id) {
return async (dispatch) => {
try {
const response = await findOne(id)
if(response && response.body) {
const company = response.body
dispatch(companyReceived(company))
}
} catch(err) {
console.log("failed request in authenticate thunk action")
console.log(`error details: ${err.status} /n ${err}`)
}
}
}
Container
......
import { fetchCompany } from '../../client/actions/company/CompanyAsyncActions'
class InterviewContainer extends Component {
async componentDidMount() {
await fetchCompany(this.props.params.companyId)
}
render(){
return (this.props.company && <Interview className='ft-interview' company={this.props.company} />)
}
}
const mapStateToProps = state => ({
company: state.company.company
})
const mapDispatchToProps = {
fetchCompany: fetchCompany
}
export default connect(mapStateToProps, mapDispatchToProps)(InterviewContainer)
In the past, I haven't passed (dispatch) as a prop to mapDispatchToProps and it worked fine. But I see everyone else is doing so. How was my code working in the past if I wasn't doing that? And why isn't this working this time around in the example above?
Taking a look at another async action thunk container and call example, this is working completely fine, and I'm calling it the same way in another container
container
class HomePageContainer extends Component {
constructor(){
super()
}
async componentDidMount() {
await this.props.fetchFeaturedCompanies()
await this.props.fetchCompanies()
await this.props.fetchCountries()
}
render(){
return (<HomePage className='ft-homepage'
featuredCompanies={this.props.featuredCompanies}
countries={this.props.countries}
companies={this.props.companies}
/>)
}
}
const mapStateToProps = state => ({
countries: state.country.countries,
companies: state.company.companies,
featuredCompanies: state.company.featuredCompanies
})
const mapDispatchToProps = {
fetchCountries: fetchCountries,
fetchCompanies: fetchCompanies,
fetchFeaturedCompanies: fetchFeaturedCompanies
}
export default connect(mapStateToProps, mapDispatchToProps)(HomePageContainer)
thunk action
export function fetchCompanies() {
return async (dispatch, getState) => {
const response = await find()
if(response && response.body) {
const companies = response.body
dispatch(companiesReceived(companies))
}
}
}
In componentDidMount of InterviewContainer you're accidentally calling the imported fetchCompany, instead of this.props.fetchCompany.