I am using React-native, axios after i learn how to install jwt and apply to my React native i see without state management i have to pass jwt token that fetch from login auth as props down multiple lvl that what i start hating. so i research and see about redux, redux-thunk, redux-saga
and i choose redux-saga
.
Can any guide me to setup redux-sagas like Folder structure, code split example i had 2 page like product, firmware.
in redux-thunk
action/
/actionProduct.js
/actionFirmware.js
reducer/
/index.js
/productReducer.js
/firmwareReducer.js
store.js
index.js
but in redux-sagas i'm start to confuse it has action, reducer, sagas and store is difference setup too.
const sagaMiddleware = createSagaMiddleware();
// mount it on the Store
const store = createStore(reducer, applyMiddleware(sagaMiddleware));
// then run the saga
sagaMiddleware.run(mySaga);
export default store;
in redux-thunk i never see simillar syntax like this sagaMiddleware.run(mySaga);
Do i need to create sagas folder and add 2 sagas like productSagas, firmwareSagas ?
Do i need to write 2 line like
sagaMiddleware.run(productSagas);
sagaMiddleware.run(firmwareSagas);
export default store;
or we can setup dynamic store ? and how can i do it ? Thank in advanced.
New Topic
i'm not sure i have setup this properly or not let see my setup. Store.js
const sagaMiddleware = createSagaMiddleware();
const store = createStore(
rootReducer,
window.devToolsExtension && process.env.NODE_ENV !== 'production' ?
compose(
applyMiddleware(sagaMiddleware),
window.devToolsExtension(),
) :
applyMiddleware(sagaMiddleware),
);
sagaMiddleware.run(rootSaga);
export default store;
rootSaga file
export default function* rootSaga() {
yield all([
firmwareWatcher(),
productWatcher(),
]);
}
rootReducer
export default const rootReducer = combineReducers({
firmware,
porduct,
});
App.js
class App extends Component {
componentDidMount() {
const { dispatch } = this.props;
dispatch({ type: "FIRMWARE_REQUEST"});
dispatch({ type: 'PRODUCT_REQUEST'});
}
....
}
const mapStateToProps = (state) => {
console.log(state);
return { ... };
};
this is console.log(state) inside mapStateToProps i get and i consone.log in switch case to know ACTION TYPE
PRODUCT_SUCCESS
{type: "PRODUCT_SUCCESS", payload: {…}, @@redux-saga/SAGA_ACTION: true}
{firmware: {…}, porduct: {…}}
FIRMWARE_SUCCESS
{type: "API_CALL_SUCCESS", payload: {…}, @@redux-saga/SAGA_ACTION: true}
default
{firmware: {…}, porduct: {…}}
{firmware: {…}, porduct: {…}}
|
V
firmware : {fetching: false, dog: null, error: null, data: "https://dog.ceo/api/img/retriever-golden/n02099601_2495.jpg"}
porduct :
data : {id: 120, name: "A1", image: "a1_12-16-2017-1513389068.jpg", price: "28.00", status: 1, …}
First we import our Saga from the ./sagas module. Then we create a middleware using the factory function createSagaMiddleware exported by the redux-saga library. Before running our helloSaga , we must connect our middleware to the Store using applyMiddleware . Then we can use the sagaMiddleware.
We specifically recommend organizing your logic into "feature folders", with all the Redux logic for a given feature in a single "slice/ducks" file".
Redux Saga is a middleware library used to allow a Redux store to interact with resources outside of itself asynchronously. This includes making HTTP requests to external services, accessing browser storage, and executing I/O operations. These operations are also known as side effects.
Such a powerful & elegant tool as Redux-Saga, a Redux side effect manager, is said to be deprecated, and no longer being maintained, starting from Jan 27, 2021.
THe way we are going to use Sagas with Redux is our application is with generators. So generators are functions that contains state and is very similar to our closure in JS. Where a function when run creates it's private variables so that it could be used later and can't be accessed by the scope outside it's own closure.
There is no single answer, but as per official guidelines, we have to create necessary folders and files to structure the Redux app. Below is the sample folder structure for the simple demo app created using React and Redux.
However, there are a few common patterns that most Redux developers tend to use: Rails-style: separate folders for “actions”, “constants”, “reducers”, “containers”, and “components” "Feature folders" / "Domain"-style : separate folders per feature or domain, possibly with sub-folders per file type
So what is a redux? A redux a store a place that contains the state of our application. It's like state in react but with a lot more complexity and functions. But before we can create our Redux we have to first create Types and actions.
You don't need to run the individual sagas, since you are using sagaMiddleware all your actions will pass through your sagas. I think you're on the right track - here is how I would set up sagas.
Create a saga for each of your async components, productSaga.js
and firmwareSaga.js
.
Then create an index file for your sagas index-sagas.js
. This will import all the sagas from around your project and export them for use in your index.js
file.
/// index-sagas.js ///
import productWatcher from './components/product/product-saga.js';
import firmwareWatcher from './components/firmware/firmware-saga.js';
export default function* IndexSagas() {
yield [
productWatcher(),
firmwareWatcher(),
]
}
/// end of file ///
This is what you import at the top of index.js
:
/// index.js ///
import IndexSagas from './index-sagas.js'
...
/// end of file ///
In product-saga.js
and firmware-saga.js
create a couple generator functions
/// product-saga.js ///
import { PRODUCT_ACTION } from './constants';
import { productActionSuccess, productActionError } from './actions';
export default function* productWatcher() {
yield [
takeLatest(PRODUCT_ACTION, productActionFlow)
]
}
// This will be triggered any time PRODUCT_ACTION is dispatched and it
// will call the productActionFlow generator. This is
// where your async logic lives
function* productActionFlow(action) {
try {
const result = yield call(productGETRequest, action)
// productGETRequest is a function elsewhere in this file that
// will make your GET request
yield put(productActionSuccess(result))
// productActionSuccess is the action imported above
} catch (error) {
yield put(productActionError(error)
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With