in this part
https://redux.js.org/basics/store#dispatching-actions
let's verify our program works! Even without any UI, we can already test the update logic.
is there anyone can tell me how to test the update logic?
node doesn't the import syntax
When they say, "Even without any UI, we can already test the update logic" look at lines 12 and 13 in the code snippet below that:
// Note that subscribe() returns a function for unregistering the listener
const unsubscribe = store.subscribe(() => console.log(store.getState()))
They are saying that even without any UI changing along with this change of state, you can see the change of state being logged to the console. They then show a screenshot of the Redux chrome extension which is another way you can see the redux state changing.
If the import syntax is giving you trouble, try the Es5 CommonJS syntax, something like this:
var createStore = require('redux').createStore
From the redux docs.
Hope this helps.
Related
Hello this is my first question. I am trying to set up a project where modules along with the redux and sagas will be injected into the main app, using redux-injectors. In my sagas I want to use yield select, to check if an action has updated the state and then carry on. For example, when I post an image, I want to make sure there were no errors in posting the file and then move on. I use the following function:
export const imageErrors = (state: RootState): IImagesErrorState => state.image.errors
and then in the saga.ts file I use it as such:
if (imagesErrors?.postImageError !== null) {
throw imagesErrors.postImageError
}
this works fine as long as the state.image exists in the root state from the beginning. However, how do I do that when I want to inject this state later on using useInjectReducer and useInjectSaga? I obviously get an error
Property 'image' does not exist on type 'Reducer<CombinedState<{ user: CombinedState<{ auth: IAuthState; errors: IErrorState; }>; }>, AnyAction>'.ts(2339)
So how do we handle selectors of specific pieces of state, since state does not yet include them?
Thank you so much.
Can't talk about the Typescript part of things, but in terms of architecture you've got two options.
One is the obvious - that is to add conditions or ? everywhere to avoid errors from accessing missing properties, but that can get tedious quickly.
The other probably better option is to rethink your state & application chunks. What is this saga that is accessing state that isn't existing yet? Does it need to run before you have such state? If not, let's move the saga to the same chunk as the reducer. In the opposite case, where you need the saga to be running e.g. as part of the runtime chunk, then perhaps the image state should be in the runtime chunk as well.
I'm new to all of these technologies, but as far as I understand it, you can use React Native with Redux and Firebase without react-redux-firebase. You could just use
react
react-native
redux
react-redux
react-native-firebase
Then you load data from Firebase (e.g. Firestore) and put the data in a reducer so it gets merged into the redux store.
Why do I need react-redux-firebase? What problem does it solve?
I have tried its docs, but they seem to be written for someone who is already familiar with its goals. They do not really explain, and when reading the examples, I do not understand why I specifically need react-redux-firebase instead of the setup listed above.
Firebase is on your state, listen to it an modify it, it will change your Firebase database. After the data on the database is changed the components listening will change as well.
This will create an item in the database
updateTodo: props => () => {
return firebase.update(`todos/${params.todoId}`, { done: !todo.isDone })
}
So any component listening to that node will get updated:
connect((state) => ({
todos: state.firebase.data.todos,
// profile: state.firebase.profile // load profile
}))
It solves the problem of having multiple sources of truth, your Firebase database is your only source of truth, otherwise, you change your local data and then you update the data online and then if it works nothing else but if it fails you have to update the local data again
I'm working on a Symfony application and just got SSR for JS working using https://github.com/spatie/server-side-rendering. So far I only worked with "readymade" SSR solutions for React, but currently I'm trying to use hyperHTML/viperHTML and am facing a few issues that so far I wasn't able to solve by looking at the available docs/examples.
My current test snippet is this:
const viperHTML = require('viperhtml');
class Component extends viperHTML.Component {
constructor(props) {
super();
this.props = props;
}
render() {
return this.html`
<h1>Hello, ${this.props.name}</h1>`;
}
}
console.log(new Component({ name: 'Joe' }).render().toString());
The thing here is that without explicitly calling render() I get no output. Looking at some of the official examples this shouldn't be necessary, at least not with Component. I already tried using setState() in the constructor, for example, but no difference.
Also, without using both, console.log() and toString(), I get no output either. Which is unexpected. I get that toString() might be necessary here (without it a <buffer /> is being rendered), but the console.log() seems odd. This might not be related to viperHTML at all of course. But instantiating the component is the only thing I expected to be necessary.
It's also not clear to me yet how I can write an isomorphic/universal component, i.e. one file which has the markup, event handlers etc., gets rendered on the server and then hydrated on the client. When I add an inline event handler as per the docs (https://viperhtml.js.org/hyperhtml/documentation/#essentials-6) it actually gets inlined into the rendered markup, which is not what I want.
I checked hypermorphic and the viperNews app, but that didn't really help me so far.
In case it helps, you can read viperHTML tests to see how components can be used.
The thing here is that without explicitly calling render() I get no output.
Components are meant to be used to render layout, either on the server or on the client side. This means if you pass a component instance to a hyper/viperHTML view, you don't have to worry about calling anything, it's done for you.
const {bind, Component} = require('viperhtml');
class Hello extends Component {
constructor(props) {
super().props = props;
}
render() {
return this.html`<h1>Hello, ${this.props.name}</h1>`;
}
}
console.log(
// you need a hyper/viperHTML literal to render components
bind({any:'ref'})`${Hello.for({ name: 'Joe' })}`
// by default you have a buffer to stream in NodeJS
// if you want a string you need to use toString()
.toString()
);
Since NodeJS by default streams buffers, any layout produced by viperHTML will be buffers and, as such, can be streamed while it's composed (i.e. with Promises as interpolation values).
It's also not clear to me yet how I can write an isomorphic/universal component, i.e. one file which has the markup, event handlers etc., gets rendered on the server and then hydrated on the client.
The original version of hyperHTML had a method called adopt() which purpose was to hydrate live nodes through same template literals.
While viperHTML has an viperhtml.adoptable = true switch to render adoptable content, hyperHTML adopt feature is still not quite there yet so that, for the time being, you can easily share views between SSR and the FE, but you need to either take over on the client once the SSR page has landed or react, for the very first time, differently and take over on the client at distance.
This is not optimal, but I'm afraid the hydration bit, done right, is time consuming and I haven't found such time to finalize it and ship it.
That might be hyperHTML v3 at this point.
I hope this answer helped understanding how viperHTML works and what's the current status.
Project (Todolist) was created with immutable library, source here
Store structure: project have many tasks, In redux store: State - map, projects, tasks - Records
When I asyncly remove project ...
export const removeProject = project => (dispatch) => {
if (!isProjectExist(project)) return Promise.resolve()
return projectService
.delete(project)
.then(
() => {
dispatch(remove(project))
console.log("post removeProject resolved")
},
handleError,
)
}
.... that was created after initialization - it will be deleted and properly unmounted, but when project was passed as initialState - ProjectList will not be rerendered, and ProjectItem try to render itself with stale data, and fail, as in picture
It have tests
It looks like reducer returs changed data, but I use immutablejs, and previously i use normalizr-immutable, but I thought that source of issue in this library and write my own normalizeInitialState (source), it did not help, now I think that maybe source of problem in redux-immutable
I struggled entire day on solving of this problem
creator of redux says
I don't think this is something we can fix. React state changes are
asynchronous and React may (or may not) batch them. Therefore, the
moment you press “Remove”, the Redux store updates, and both Item and
App receive the new state. Even if the App state change results in
unmounting of Items, that will happen later than mapStateToProps is
called for Item.
Unless I'm mistaken, there is nothing we can do. You have two options:
Request all required state at App (or a lower, e.g. ItemList) level
and pass it down to “dumb” Items. Add safeguards to mapStateToProps
for “currently unmounting” state. For example, you may return null
from render in this case. Potentially we could have the component
generated by connect() return null from its render if mapStateToProps
returned null. Does this make any sense? Is this too surprising?
Hm, I never saw stubs like return (<div></div>) or safeguards in mapStateToProps in others code
markerikson
I'm not entirely sure I follow what exactly your problem is, but as a
guess: it sounds like the child component is re-rendering before the
parent is. This is a known issue with React-Redux v4 and earlier. The
v5 beta fixes that issue. Try installing react-redux#next and see if
that takes care of your problem.
I would like many different redux actions in my app to all trigger common functionality in a specific reducer. I would like to avoid having to either repeat some flag in every action creator (like doThing: true) that the reducer looks for. I also don't want to have to have the reducer just look for every individual action that falls into this category, since that also requires someone to remember to do this every time they add a new action, like adding the flag.
I was thinking of dispatching a second action every time one of these actions is going to be dispatched. This would not be hard to do, but I'd rather not have 2 actions dispatched every time one thing happens. It seems like it would pollute the state history.
Is there a common way of solving this problem?
For more context to my specific problem, the specific feature is related to the API client my app uses to talk to our API. On every successful response, we'd like to do something in a reducer to update the state, and on every failed response, we'd like to do something else.
There are many different success and failure actions (such as ITEM_FETCH_SUCCESS or WIDGET_UPDATE_FAILURE), and adding a flag to all of them would be hard to remember to do when new ones are added.
Since all api requests go through a single function, that function COULD dispatch generic REQUEST_SUCCESS and REQUEST_FAILURE actions. But this would mean every response from the server would dispatch 2 actions (REQUEST_SUCCESS and ITEM_FETCH_SUCCESS). This is obviously not ideal since it would mean many more actions in my state history.
Assuming the generic REQUEST_SUCCESS and REQUEST_FAILURE actions are updating their own specific portions of the state-tree then it is fine to dispatch them as distinct actions. Doing this does not necessarily imply the pollution of your state history but can simply be a better description of the app's intentions.
ITEM_FETCH_SUCCESS: Change state for item
REQUEST_SUCCESS: Change state for request
WIDGET_UPDATE_FAILURE: Change state for widget
REQUEST_FAILURE: Change state for request
You can see that whilst the actions are intimately related, they are not necessarily the same thing as they change different parts of the state tree.
Accepting this, the question is: How best to implement the action-pairs so that adding new actions does not mean remembering to add its corresponding REQUEST_* partner?
I would consider applying a simple redux middleware component. This could intercept the return from your api and dispatch the appropriate REQUEST_* action automatically.
Here is an example from some live code. This middleware intercepts a disconnect event raised by a websocket and automatically dispatches a custom action as a result. It at least shows the principle:
//Dispatch a disconnect action when the websocket disconnects
//This is the custom action provided by the middleware
import io from 'socket.io-client'
import { actions } from './action'
const websocket = ({ websocketUrl }) => store => {
const socket = io(websocketUrl)
socket.on('disconnect', () => store.dispatch(actions.disconnect()))
}
export default websocket
//Apply the custom middleware via the redux createStore function
//Also include the thunk middleware because it is useful
import { applyMiddleware } from 'redux'
import thunk from 'redux-thunk'
import websocket from './middleware'
function websocketize (opts) {
return createStore => (reducers, initial, enhancer) => {
const middleware = applyMiddleware(thunk, websocket(opts))
return createStore(reducers, initial, middleware)
}
}
export default websocketize
// Create the top-level redux store passing in the custom middleware enhancer
const opts = {websocketUrl: env.WEBSOCKET_URL}
const store = createStore(reducers, websocketize(opts))
This implementation keeps everything inside your reducers as opposed to having logic outside in an interception(middleware). Both ways are valid.
Try a sub-reducer pattern. I usually feel gross when I see it used(because it is usually used wrong), but your situation sounds perfect.
Extract duplicate functionality out of your reducers to one single
sub-reducer.
Then pass that reducer as a function to all others that need it.
Then pass the action and state onto the sub-reducer.
The sub-reducer does it's thing and returns that slice of state to
your parent reducer to allow you to do whatever you want with it
there (ie return it, mutate some more, some logic).
Also if you are tired of worrying about typing out "all the stuff" for async then I highly recommend you try out redux-crud.js
It also is possible and a simple way to do that would be to give every action to one reducer and let it do that common mutation, in a single case:
case actionOne
actionTwo
actionThree
actionFour: {
//do common stuff here
}
. But you said it is not duplicated, it is similar, which means your case becomes complicated by branching logic. I also don't recommend this. Keep cases simple so you can easily catch invalid mutations. This should be a super power of redux that it is easy to catch mutation errors. And for this reason and many others I don't recommend normalizing data in the front end.