javascript - react + Redux : reducer won't reload component

标签 javascript reactjs redux babeljs

我编写了一个通用的 Table 组件,使用两个不同的数据集实例化了两次。我使用 Redux 存储来水合 props,并尝试在单击一行时删除它。

组件显示良好,onClick 函数被触发,reducer 被调用。新返回的状态返回之前没有单击该元素的状态。

我的问题是组件没有重新渲染。 根据故障排除页面(http://redux.js.org/docs/Troubleshooting.html),似乎我没有改变以前的状态(也许我只是不明白该怎么做),我正在调用dispatch()函数,我的mapStateToProps似乎是因为数据在页面加载时很好地显示。

我尝试在reducer.js >表函数中定义初始状态,而不是使用createStore函数,我尝试将“tables”reducer拆分为“domains”和“hosts”reducer(重复代码),我试图不这样做使用combineReducers(),因为我只有一个(但将来我会有更多),而且我尝试了很多东西,所以我不记得了。

我敢打赌这不是什么大问题,但我只是无法弄清楚发生了什么。你能帮我吗 ?非常感谢。

<小时/>

reducer .js

import { combineReducers } from 'redux'
import { DELETE_DOMAIN, DELETE_HOST } from './actions'

function deleteItem(state, index) {
    let newState = Object.assign({}, state)

    newState.items.splice(index, 1)

    return newState
}

function tables(state = {}, action) {
    switch (action.type) {
        case DELETE_HOST:
            return Object.assign({}, state, {
                hosts: deleteItem(state.hosts, action.host)
            })

        case DELETE_DOMAIN:
            return Object.assign({}, state, {
                domains: deleteItem(state.domains, action.domain)
            })

        default:
            return state
    }
}

const reducers = combineReducers({
    tables,
})

export default reducers

actions.js

export const DELETE_DOMAIN = 'DELETE_DOMAIN'
export const DELETE_HOST = 'DELETE_HOST'

export function deleteDomain(domain) {
    return { type: DELETE_DOMAIN, domain }
}

export function deleteHost(host) {
    return { type: DELETE_HOST, host }
}

index.js

import React from 'react';
import ReactDOM from 'react-dom';
import App from './app';
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import reducers from './reducers'

const initialState = {
    tables: {
        domains: {
            headers: {
                id: 'Id',
                domain: 'Domain',
                host: 'Hoster',
            },
            items: [
                {
                    id: 1,
                    domain: 'dev.example.com',
                    host: 'dev',
                },
                {
                    id: 2,
                    domain: 'prod.example.com',
                    host: 'prod',
                }
            ]
        },
        hosts: {
            headers: {
                id: 'Id',
                label: 'Label',
                type: 'Type',
                hoster: 'Corporation',
            },
            items: [
                {
                    id: 1,
                    label: 'Server 1',
                    type: 'Server type',
                    hoster: 'Gandi',
                },
                {
                    id: 2,
                    label: 'Server 2',
                    type: 'Server type',
                    hoster: 'OVH',
                }
            ]
        }
    }
}

let store = createStore(reducers, initialState)

ReactDOM.render(
    <Provider store={store}>
        <App />
    </Provider>,
    document.getElementById('root')
);

app.js

import React from 'react';
import Domains from './modules/domains.js';
import Hosts from './modules/hosts.js';
import Nav from './modules/nav.js';
import {
  BrowserRouter as Router,
  Route,
} from 'react-router-dom'

export default class App extends React.Component {
    render() {
        return (
            <Router>
                <div className="container-fluid col-md-6">
                    <Nav />
                    <Route path="/domains" component={Domains}/>
                    <Route path="/hosts" component={Hosts}/>
                </div>
            </Router>
        );
    }
}

域名.js

import React from 'react';
import Table from './../components/table.js';
import { connect } from 'react-redux'
import { deleteDomain } from './../actions'

const mapStateToProps = (state) => {
    return state.tables.domains
}

const mapDispatchToProps = (dispatch) => {
    return {
            onRowClick: (id) => {
                dispatch(deleteDomain(id))
            }
        }
}

class DomainsView extends React.Component {
    render() {
        return (
            <Table headers={this.props.headers} items={this.props.items} onRowClick={this.props.onRowClick} />
        )
    }
}

const Domains = connect(
    mapStateToProps,
    mapDispatchToProps,
)(DomainsView)

export default Domains

hosts.js 与domains.js相同,但const/类名和props不同

最佳答案

由于你的 redux 状态是深度嵌套的,Object.assign 不会产生实际的重复。尽管状态本身是重复的,但它的值是对与以前相同的对象的引用。因此,深度嵌套的对象不会重复。我的建议是在你的reducer中使用lodash的merge方法而不是Object.assign。通过 npm 安装 lodash,然后:

import { combineReducers } from 'redux'
import { merge } from 'lodash'
import { DELETE_DOMAIN, DELETE_HOST } from './actions'

function deleteItem(state, index) {
    let newState = merge({}, state);

    newState.items.splice(index, 1)

    return newState
}

function tables(state = {}, action) {
    let newState;
    switch (action.type) {
        case DELETE_HOST:
            newState = merge({}, state);
            newState.hosts = deleteItem(state.hosts, action.host)
            return newState;
        case DELETE_DOMAIN:
            newState = merge({}, state);
            newState.domains = deleteItem(state.domains, action.domain)
            return newState;
        default:
            return state
    }
}

const reducers = combineReducers({
    tables,
})

export default reducers

关于javascript - react + Redux : reducer won't reload component,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44393330/

相关文章:

javascript - Kendo Grid with kendo下拉列表

javascript - React - 从嵌入式组件中的数组获取内容

javascript - 从选择中获取值(value)——REACT

javascript - saga 的高阶函数为 sagan 函数注入(inject)参数

javascript - 无法在React中输入InputType 'text'

node.js - 如何避免使用 redux 在 react-apollo SSR 中重新获取客户端?

javascript - 如何彻底处理提取中的预期错误?

javascript - 使用 FullCalendar.js 在多个日历上创建事件

javascript - 在javascript中的方法中访问对象的成员

javascript - 使用旧状态的 PayPal 智能支付按钮