Как обрабатывать реквизиты слишком медленно для обновления? - PullRequest
1 голос
/ 14 октября 2019

Написал компонент React Hooks, который отображает случайно выбранные цитаты из Redux.

Я изо всех сил пытаюсь прочитать цитату из реквизита при первом рендеринге (вместо этого мне пришлось написать оператор switch в JSX для чтения из локального состояния компонента React при первом рендеринге).

Все хорошо, чтобы читать из реквизита, когда один нажимает на кнопку, чтобы получить новую случайную цитату (т.е. много после первого рендера). Думаю, реквизиты слишком медленно обновляются.

Указатели о том, как с этим бороться, приветствуются. То, что я сделал, - это скорее хак, поскольку я вообще не читаю в магазине Redux при первом рендере.

const defaultState = {};

const NEW_QUOTE = "NEW_QUOTE"

const newQuoteActionCreator = (quoteObject) => {
  return {
    type: NEW_QUOTE,
    payload: quoteObject
  };
};

const getNextQuoteReducer = (state = defaultState, action) => {
  switch (action.type) {
    case NEW_QUOTE:
       return {
         ...state,
         data: action.payload
       };
    default:
       return state;
  }
};

const store = Redux.createStore(getNextQuoteReducer);

const quotes = [
    {
        quoteText:"\"AAAAAA.\"",
        quoteAuthor:"BBBB",
    },
    {
        quoteText:"\"CCCCC.\"",
        quoteAuthor:"DDDD",
    }
];

Бит React:

const QuoteBox = ({ text, author }) => { //destructuring
  return (
    <React.Fragment>
      <div className="quotable-square">
        <div className="content">
          <div id="text">{text}</div>
          <div id="author" className="author">{author}</div>
        </div>
      </div> 
    </React.Fragment>
  )
}

const Button = ({ onClick, title }) => {
   return (
      <button className="new-quote" onClick={onClick}>{title}</button>
   )
}

const App = (props) => {
  const [quote, setQuote] = React.useState(() => {
    const initialQuote = quotes[Math.floor(Math.random() * quotes.length)];
    return {
      data: initialQuote
    }
  });

  const chosenRandomQuoteToState = () => {
    let chosenQuote = randomQuoteFunction(quotes);
    props.selectNewQuote(chosenQuote);
  }

  return (
    <React.Fragment>
      <div className="container">
        <div id="quote-box">
          <QuoteBox text={(() => {
            switch (typeof props.currentQuote.data) {
              case "undefined":   return quote.data.quoteText 
              default:            return props.currentQuote.data.quoteText;
            }
          })()}/>
          <div className="actions">
            <Button id="new-quote" title="Get New Quote" onClick={chosenRandomQuoteToState} />
          </div>
        </div>    
      </div> 
    </React.Fragment>   
  )
}

Бит React Redux:

const Provider = ReactRedux.Provider;

const mapStateToProps = (state) => {
  return {
    currentQuote: state
  }

const mapDispatchToProps = (dispatch) => {
    return {
        selectNewQuote: function(quoteToBeNewQuote) {
          dispatch(newQuoteActionCreator(quoteToBeNewQuote));
        }
    }
}

const connect = ReactRedux.connect

const Container = connect(mapStateToProps, mapDispatchToProps)(App);

const AppWrapper = () => {
    return (
      <Provider store= {store}>
        <Container />
      </Provider>
    );
};

ReactDOM.render(<AppWrapper />, document.getElementById('app'));

Новичок, так что будь полегче со мной:)

Ответы [ 2 ]

0 голосов
/ 14 октября 2019

Попробуйте что-то вроде этого:

const initialState = {
  quotes: [
    {
      quoteText: '"AAAAAA."',
      quoteAuthor: 'BBBB',
    },
    {
      quoteText: '"CCCCC."',
      quoteAuthor: 'DDDD',
    },
  ],
}; //renamed defaultState

const mapStateToProps = state => {
  //state should hold data, container (map state) should
  //  create values based on that data
  const { quotes } = state;
  return {
    currentQuote:
      quotes[Math.floor(Math.random() * quotes.length)],
  };
};
const mapDispatchToProps = dispatch => ({
  selectNewQuote: dispatch(newQuoteActionCreator()),
});

const getNextQuoteReducer = (
  state = defaultState,
  action
) => {
  switch (action.type) {
    case NEW_QUOTE:
      return {
        ...state,
        quotes: [...state.quotes], //forces app container to re run
      };
    default:
      return state;
  }
};

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

0 голосов
/ 14 октября 2019

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

const App = (props) => {
  useEffect(() => {
    chosenRandomQuoteToState();
  }, []);

  const chosenRandomQuoteToState = () => {
    let chosenQuote = randomQuoteFunction(quotes);
    props.selectNewQuote(chosenQuote);
  };

  const currentQuote = props.currentQuote.data;

  return (
    <React.Fragment>
      <div className="container">
        <div id="quote-box">
          {currentQuote && <QuoteBox text={currentQuote}/>}
          <div className="actions">
            <Button id="new-quote" title="Get New Quote" onClick={chosenRandomQuoteToState} />
          </div>
        </div>    
      </div> 
    </React.Fragment>   
  )
}
...