Redux работает некорректно

Я только что немного изучил react-redux и застрял на таких проблемах, которые я не могу понять и исправить, по крайней мере, за 4 дня.

  1. Первая проблема стоит и ее можно увидеть в консоли инспекторов (я использую Chrome). У меня есть обработчик событий на <div> внутри компонента реакции. Он должен вызываться при событии onClick, но он срабатывает при каждой загрузке или перезагрузке сайта.

  2. Во-вторых, стоит где-то рядом с функцией редуктора. В консоли (инструменты разработчика) мне сказано, что редукторы получили действие TOGGLE_TILE и вернули undefined вместо объекта. Следует заметить, что редуктор успешно получает состояние, свойства действия и выполняет некоторые операции внутри, но в результате ничего нормального не возвращается.

    Код моего редуктора, действия, основные компоненты, контейнер, компоненты и функции представления предоставляют. Пожалуйста, ответьте развернутым, насколько вы можете, я хочу понять, что не так, и не повторять эту ошибку внутри кода дважды.

ТАКЖЕ! Я использую промежуточное ПО redux-thunk (вы знаете, для функциональных обратных вызовов внутри действий). Внутри у меня есть:

index.js - основной компонент

const store = createStore(reducer, applyMiddleware(thunk));

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

actions.js

export function toggle(id){
    return{
        type: 'TOGGLE_TILE',
        id
    };
}

export function toggleTile(id){
    return dispatch => {
        console.info('toggling');
        dispatch(toggle(id));
    };
}

tile.js - Редуктор

var i = 0;

function tiles(state = tilesContainer, action){
    var openedTiles = [];
    switch (action.type) {
        case 'TOGGLE_TILE':
            if (i < 2){  
                console.info('i: '+i);  
                state.map((value) => {
                    var newOpen;
                    if (!value.opened && action.id === value.id){  
                        newOpen = Object.assign({}, value, {
                            opened: !value.opened
                        });  
                        openedTiles.push(newOpen);
                        i++;
                        console.info(i, value.opened, newOpen, openedTiles);
                    }
                    return newOpen, i;
                });
            }else if (i === 2){
                var curr, prev;
                openedTiles.map((value) => {
                    if (!prev){
                        prev = value;
                    }else{
                        curr = value;
                        console.info("Prev and curr: "+prev, curr);
                        if (curr.name === prev.name){
                            var currRes = Object.assign({}, curr, {
                                disappeared: !curr.disappeared
                            });
                            var prevRes = Object.assign({}, prev, {
                                disappeared: !prev.disappeared
                            });
                            return {currRes, prevRes}; 
                        } else {
                            let currRes = Object.assign({}, curr, {
                                opened: !curr.opened
                            });
                            let prevRes = Object.assign({}, prev, {
                                opened: !prev.opened
                            })
                            return currRes, prevRes;
                        }
                    }
                });
            }else{
                return state;
            }
        default:
            return state;
    }
    console.info("tiles: "+state.forEach(value => console.info(value)));
}



const reducers = combineReducers({
    tiles
});

export default reducers;

AppContainer.jsx

const mapStateToProps = (state) => {
  return {
    tiles: state.tiles
  };
};

const mapDispatchToProps = (dispatch) => {
  return {
    toggle: id => {
      // console.info(id);
      dispatch(toggleTile(id));
    }
  };
};


class AppContainer extends Component {
  constructor(props){
    super(props);
  }
  componentDidMount(){
    
  }
  render() {
    var prop = this.props;
    console.info(prop);
    return (
      <div>
        <AppView prop = {prop} />
      </div>
    );
  }
}

export default connect(mapStateToProps, mapDispatchToProps)(AppContainer);

AppView.js

class AppView extends React.Component {
    constructor(props){
        super(props);
        this.state = {
            tiles: this.props.prop.tiles,
        };
        this.showTiles = this.showTiles.bind(this);
        this.defineRatio = this.defineRatio.bind(this);
        this.toggleTile = this.toggleTile.bind(this);
    }
    componentDidMount(){
        this.defineRatio();
        
    }
    componentWillMount(){
        
    }
    defineRatio(){
        var imgClass;
        let tile = document.querySelectorAll('img');
        tile.forEach((value) => {
            var imgSrc, imgW, imgH;
            function defineImage(imgSrc){
                var img = new Image();
                img.src = imgSrc;
                img.onload = function() {   
                    return {
                        src:imgSrc,
                        width:this.width,
                        height:this.height};
                    };
                return img;
            }
            var x = defineImage(value.src);
            x.addEventListener('load',function(){
                imgSrc = x.src;
                imgW = x.width;
                imgH = x.height;
                // console.info(value.src, imgW, imgH);
                var imgClass = (imgW / imgH > 1) ? 'wide' : 'tall';
                value.classList += imgClass;
            });
        });
    }
    toggleTile(id){
        this.props.prop.toggle(id);
    }
    showTiles(){
        const boxElems = this.state.tiles.map((value, index) => {
            var styles = {background: 'black'};
            var tileState = value.opened ? '' : styles;
            var imgState = value.opened ? 'opened ' : 'closed ';
            var elem = <img key = {value.id} src = {value.src} alt = "" className = {imgState} />;
            var boxElem = <div style = {tileState} className = "tile-box " onClick = {this.toggleTile(value.id)} key = {index}>{elem}</div>;
            return boxElem;
        });
        return boxElems;
    }
    render(){
        var tiles = this.showTiles();
        return (
            <div className = "tiles-box">
                <div className = "tiles">
                    {tiles}
                </div>
            </div>
        );
    }
}

export default AppView;
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
3
0
49
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Первую проблему можно решить, заменив

onClick = {this.toggleTile(value.id)} с onClick = {(e) => this.toggleTile(value.id)} Первый оператор просто вызывает this.toggleTile (value.id) сразу и устанавливает возвращаемое значение для события OnClick.

Что касается второго, вы ничего не возвращаете из своего редуктора, поэтому состояние не определено.

       if (i < 2){  
            console.info('i: '+i);  
            state.map((value) => {
                var newOpen;
                if (!value.opened && action.id === value.id){  
                    newOpen = Object.assign({}, value, {
                        opened: !value.opened
                    });  
                    openedTiles.push(newOpen);
                    i++;
                    console.info(i, value.opened, newOpen, openedTiles);
                }
                return newOpen, i;
            });
        }

Что это за return newOpen, i, он должен быть return newOpen, также, поскольку этот возврат находится в функции карты, вы также должны вернуть сопоставленный массив так что используйте return state.map((value) => {

Благодаря вам .. Похоже, что-то идет не так, но, в конце концов, это была моя вина, как вы, братаны, все видели .. Отсутствие внимания к деталям, что это такое ... Но также очень хороший ответ на первый вопрос, которым поделился @ PrinceHernandez. Все ваши советы помогли решить мои проблемы.

JW Jevaveh 04.05.2018 12:50

проблема, которая у вас есть, заключается в том, что вы фактически вызываете функцию внутри вашего div, поэтому она будет запускаться каждый раз, когда вы входите в представление, поэтому замените следующий код на вашем showTiles()

var boxElem = <div style = {tileState} className = "tile-box " onClick = {this.toggleTile(value.id)} key = {index}>{elem}</div>;

к этому:

var boxElem = <div style = {tileState} className = "tile-box " onClick = {e => this.toggleTile(value.id)} key = {index}>{elem}</div>;

и на самом деле это должно исправить ошибку для пункта 2.

Другие вопросы по теме