Please, check the Edit
I'm trying to implement sagas in my app.
Right now I am fetching the props in a really bad way. My app consists mainly on polling data from other sources.
Currently, this is how my app works:
I have containers which have mapStateToProps, mapDispatchToProps.
const mapStateToProps = state => {
return {
someState: state.someReducer.someReducerAction,
};
};
const mapDispatchToProps = (dispatch) => {
return bindActionCreators({someAction, someOtherAction, ...}, dispatch)
};
const something = drizzleConnect(something, mapStateToProps, mapDispatchToProps);
export default something;
and then, I have actions, like this:
import * as someConstants from '../constants/someConstants';
export const someFunc = (someVal) => (dispatch) => {
someVal.methods.someMethod().call().then(res => {
dispatch({
type: someConstants.FETCH_SOMETHING,
payload: res
})
})
}
and reducers, like the below one:
export default function someReducer(state = INITIAL_STATE, action) {
switch (action.type) {
case types.FETCH_SOMETHING:
return ({
...state,
someVar: action.payload
});
I combine the reducers with redux's combineReducers and export them as a single reducer, which, then, I import to my store.
Because I use drizzle, my rootSaga is this:
import { all, fork } from 'redux-saga/effects'
import { drizzleSagas } from 'drizzle'
export default function* root() {
yield all(
drizzleSagas.map(saga => fork(saga)),
)
}
So, now, when I want to update the props, inside the componentWillReceiveProps
of the component, I do:
this.props.someAction()
Okay, it works, but I know that this is not the proper way. Basically, it's the worst thing I could do.
So, now, what I think I should do:
Create distinct sagas, which then I'll import inside the rootSaga file. These sagas will poll the sources every some predefined time and update the props if it is needed.
But my issue is how these sagas should be written.
Is it possible that you can give me an example, based on the actions, reducers and containers that I mentioned above?
Edit:
I managed to follow apachuilo's directions.
So far, I made these adjustments:
The actions are like this:
export const someFunc = (payload, callback) => ({
type: someConstants.FETCH_SOMETHING_REQUEST,
payload,
callback
})
and the reducers, like this:
export default function IdentityReducer(state = INITIAL_STATE, {type, payload}) {
switch (type) {
case types.FETCH_SOMETHING_SUCCESS:
return ({
...state,
something: payload,
});
...
I also created someSagas:
...variousImports
import * as apis from '../apis/someApi'
function* someHandler({ payload }) {
const response = yield call(apis.someFunc, payload)
response.data
? yield put({ type: types.FETCH_SOMETHING_SUCCESS, payload: response.data })
: yield put({ type: types.FETCH_SOMETHING_FAILURE })
}
export const someSaga = [
takeLatest(
types.FETCH_SOMETHING_REQUEST,
someHandler
)
]
and then, updated the rootSaga:
import { someSaga } from './sagas/someSagas'
const otherSagas = [
...someSaga,
]
export default function* root() {
yield all([
drizzleSagas.map(saga => fork(saga)),
otherSagas
])
}
Also, the api is the following:
export const someFunc = (payload) => {
payload.someFetching.then(res => {
return {data: res}
}) //returns 'data' of undefined but just "return {data: 'something'} returns that 'something'
So, I'd like to update my questions:
My APIs are depended to the store's state. As you may understood, I'm building a dApp. So, Drizzle (a middleware that I use in order to access the blockchain), needs to be initiated before I call the APIs and return information to the components. Thus,
a. Trying reading the state with getState(), returns me empty contracts (contracts that are not "ready" yet) - so I can't fetch the info - I do not like reading the state from the store, but...
b. Passing the state through the component (this.props.someFunc(someState), returns me
Cannot read property 'data' of undefined
The funny thing is that I can console.log the state (it seems okay) and by trying to just `return {data: 'someData'}, the props are receiving the data.- Should I run this.props.someFunc() on, for e.g., componentWillMount()? Is this the proper way to update the props?
Sorry for the very long post, but I wanted to be accurate.
Edit for 1b: Uhh, so many edits :) I solved the issue with the undefined resolve. Just had to write the API like this:
export function someFunc(payload) {
return payload.someFetching.then(res => {
return ({ data: res })
})
}