S
S
shading2019-12-18 19:37:39
React
shading, 2019-12-18 19:37:39

React-redux doesn't rerender component on state change?

Git link - https://github.com/Shading29/tosterr/blob/master/s...
When the search state changes, the table is not redrawn.
The state definitely changes correctly
. Apparently, I went the wrong way)

Answer the question

In order to leave comments, you need to log in

2 answer(s)
N
Nikolay Matyushkin, 2019-12-18
@Devilz_1

Your logic here is as follows:
When entering some characters, the filterUsers function is called, which in turn dispatches the input value to the store, replacing the search parameter each time. Each time dispatch is called, the state is re-rendered, which changes depending on the dispatch. In your example, you update the state of the search parameter when the users parameter retains its state from when you last dispatched it (i.e. called the loadUsers function), because the filterUsers function refers to the USERTABLE_FILTER_USERS case, and to the case, which directly changes the state of the users parameter (USERSTABLE_LOAD_USERS) it does not apply.
Try like this. The solution is certainly not perfect, but you should see the difference. Replace your USERTABLE_FILTER_USERS case with the one below.

case USERTABLE_FILTER_USERS:
                return {
                    ...state,
                    search: action.payload,
                    users: filteredUsers(state.users)
                }

C
camelCaseVlad, 2019-12-18
@camelCaseVlad

Looked at your turnips:
Here's what I did.
First, you haven't set up storeredux devtools either.
I did this in your index, but I recommend moving this functionality to a separate file (install the missing packages):

// src/index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import * as serviceWorker from './serviceWorker';
import { applyMiddleware, compose, createStore } from 'redux';
import { createLogger } from 'redux-logger';
import rootReducer from "./store/reducers";
import { Provider } from "react-redux"
import {BrowserRouter} from "react-router-dom";

function configureStore(initialState) {
  const windowExist = typeof window === 'object';
  const loggerMiddleware = createLogger({
    colors: {
      title: (color) => windowExist && color,
      prevState: (color) => windowExist && color,
      action: (color) => windowExist && color,
      nextState: (color) => windowExist && color,
      error: (color) => windowExist && color
    }
  });
  const composeEnhancers = (windowExist &&
    window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || // eslint-disable-line no-underscore-dangle
    compose;
  return createStore(
    rootReducer,
    initialState,
    composeEnhancers(
      applyMiddleware(loggerMiddleware),
    )
  );
}



const application = (
    <BrowserRouter>
        <Provider store={configureStore()}>
            <App/>
        </Provider>
    </BrowserRouter>
)

ReactDOM.render( application , document.getElementById('root'));

// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();

The filteredUsers functionality in the reducers folder is not needed. You already have an array with users, you can work with it directly in the component.
// src/store/UsersTable/reducers.js

import {
    USERSTABLE_LOAD_USERS,
    USERTABLE_FILTER_USERS
} from "./actions";

const defaultState = {
    users: [],
    isLoading: true,
    search: '',
}



export const userstableReducer = (state = defaultState, action) => {
        switch(action.type) {
            case USERSTABLE_LOAD_USERS:
                return {
                    ...state,
                    users: action.payload,
                    isLoading: false
                }
            case USERTABLE_FILTER_USERS:
                return {
                    ...state,
                    search: action.payload
                }
            default: return state
        }

}

Now to the question.
You already have an array, working directly with which you can reflect the desired cells
import React from "react"
import "./userstable.css"

export default class UsersTable extends React.Component {
    render() {
        const { users, filterUsers, searchValue } = this.props
        const filteredUsers = users && users.filter(user => {
            const fullName = `${user.name} ${user.surname}`;
            return fullName.toLowerCase().indexOf(searchValue.toLowerCase()) !== -1;
        });
        return (
            <React.Fragment>
                <input
                    onChange={event => filterUsers(event.target.value)}
                />
                    <table>
                        <thead>
                            <tr>
                                <th>Имя</th>
                                <th>Фамилия</th>
                                <th>Город</th>
                                <th>IP</th>
                            </tr>
                        </thead>
                        {<b>filteredUsers</b>.map(user => {
                            return (
                                <tbody key={user.id}>
                                <tr>
                                    <td> {user.name}</td>
                                    <td> {user.surname}</td>
                                    <td> {user.city}</td>
                                    <td> {user.lastloginfromip}</td>
                                </tr>
                                </tbody>

                            )
                        })}
                    </table>
            </React.Fragment>
        )
    }
}

5dfa91f33fd2a343028976.png

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question